Skip to content
Browse files

Added basic benchmark infrastructure

And also found out that 0.7.0 regresses against 0.6.0 :p

Much work to be done :D
  • Loading branch information...
1 parent 8a3c116 commit 1007396790d15c5fb9495435aea13098f677d403 @hughfdjackson committed
Showing with 22,409 additions and 0 deletions.
  1. +64 −0 benchmarks/object.js
  2. +22 −0 node_modules/benchmark/LICENSE.txt
  3. +131 −0 node_modules/benchmark/README.md
  4. +3,918 −0 node_modules/benchmark/benchmark.js
  5. +2,629 −0 node_modules/benchmark/doc/README.md
  6. +62 −0 node_modules/benchmark/package.json
  7. +9 −0 node_modules/benchmark/test/run-test.sh
  8. +2,074 −0 node_modules/benchmark/test/test.js
  9. +1 −0 node_modules/multimethod/.npmignore
  10. +22 −0 node_modules/multimethod/LICENSE
  11. +154 −0 node_modules/multimethod/README.md
  12. +19 −0 node_modules/multimethod/Rakefile
  13. +186 −0 node_modules/multimethod/docs/docco.css
  14. +116 −0 node_modules/multimethod/docs/multimethod.html
  15. +1 −0 node_modules/multimethod/index.js
  16. +10 −0 node_modules/multimethod/multimethod-min.js
  17. +181 −0 node_modules/multimethod/multimethod.js
  18. +3 −0 node_modules/multimethod/node_modules/underscore/.npmignore
  19. +22 −0 node_modules/multimethod/node_modules/underscore/LICENSE
  20. +19 −0 node_modules/multimethod/node_modules/underscore/README
  21. +1,726 −0 node_modules/multimethod/node_modules/underscore/index.html
  22. +1 −0 node_modules/multimethod/node_modules/underscore/index.js
  23. +32 −0 node_modules/multimethod/node_modules/underscore/package.json
  24. +30 −0 node_modules/multimethod/node_modules/underscore/underscore-min.js
  25. +958 −0 node_modules/multimethod/node_modules/underscore/underscore.js
  26. +29 −0 node_modules/multimethod/package.json
  27. +109 −0 node_modules/multimethod/test/multimethod-tests.js
  28. +20 −0 node_modules/multimethod/test/test.html
  29. +19 −0 node_modules/multimethod/test/vendor/jquery.js
  30. +196 −0 node_modules/multimethod/test/vendor/qunit.css
  31. +2,360 −0 node_modules/multimethod/test/vendor/qunit.js
  32. +962 −0 node_modules/multimethod/test/vendor/underscore.js
  33. +2 −0 node_modules/sinon/.npmignore
  34. +3 −0 node_modules/sinon/.travis.yml
  35. +42 −0 node_modules/sinon/AUTHORS
  36. +299 −0 node_modules/sinon/Changelog.txt
  37. BIN node_modules/sinon/GPATH
  38. BIN node_modules/sinon/GRTAGS
  39. BIN node_modules/sinon/GSYMS
  40. BIN node_modules/sinon/GTAGS
  41. +27 −0 node_modules/sinon/LICENSE
  42. +69 −0 node_modules/sinon/README.md
  43. +94 −0 node_modules/sinon/build
  44. +54 −0 node_modules/sinon/jsl.conf
  45. +336 −0 node_modules/sinon/lib/sinon.js
  46. +176 −0 node_modules/sinon/lib/sinon/assert.js
  47. +153 −0 node_modules/sinon/lib/sinon/collection.js
  48. +239 −0 node_modules/sinon/lib/sinon/match.js
  49. +423 −0 node_modules/sinon/lib/sinon/mock.js
  50. +125 −0 node_modules/sinon/lib/sinon/sandbox.js
  51. +537 −0 node_modules/sinon/lib/sinon/spy.js
  52. +355 −0 node_modules/sinon/lib/sinon/stub.js
  53. +75 −0 node_modules/sinon/lib/sinon/test.js
  54. +97 −0 node_modules/sinon/lib/sinon/test_case.js
  55. +74 −0 node_modules/sinon/lib/sinon/util/event.js
  56. +201 −0 node_modules/sinon/lib/sinon/util/fake_server.js
  57. +83 −0 node_modules/sinon/lib/sinon/util/fake_server_with_clock.js
  58. +349 −0 node_modules/sinon/lib/sinon/util/fake_timers.js
  59. +472 −0 node_modules/sinon/lib/sinon/util/fake_xml_http_request.js
  60. +27 −0 node_modules/sinon/lib/sinon/util/timers_ie.js
  61. +19 −0 node_modules/sinon/lib/sinon/util/xhr_ie.js
  62. +3 −0 node_modules/sinon/node_modules/buster-format/.travis.yml
  63. +3 −0 node_modules/sinon/node_modules/buster-format/AUTHORS
  64. +27 −0 node_modules/sinon/node_modules/buster-format/LICENSE
  65. +15 −0 node_modules/sinon/node_modules/buster-format/Readme.md
  66. +10 −0 node_modules/sinon/node_modules/buster-format/jsTestDriver.conf
  67. +199 −0 node_modules/sinon/node_modules/buster-format/lib/buster-format.js
  68. +3 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/.travis.yml
  69. +3 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/AUTHORS
  70. +28 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/LICENSE
  71. +20 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/Readme.md
  72. +17 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/jsTestDriver.conf
  73. +223 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/lib/buster-core.js
  74. +152 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/lib/buster-event-emitter.js
  75. +16 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/lib/define-version-getter.js
  76. +37 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/package.json
  77. +4 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/run-tests
  78. +564 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/test/buster-core-test.js
  79. +417 −0 ...dules/sinon/node_modules/buster-format/node_modules/buster-core/test/buster-event-emitter-test.js
  80. +3 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/vendor/buster-util/AUTHORS
  81. +28 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/vendor/buster-util/LICENSE
  82. +30 −0 node_modules/sinon/node_modules/buster-format/node_modules/buster-core/vendor/buster-util/jstdhtml
  83. +4 −0 ...s/sinon/node_modules/buster-format/node_modules/buster-core/vendor/buster-util/lib/buster-util.js
  84. +52 −0 ...es/buster-format/node_modules/buster-core/vendor/buster-util/lib/buster-util/jstestdriver-shim.js
  85. +106 −0 ...node_modules/buster-format/node_modules/buster-core/vendor/buster-util/lib/buster-util/req-res.js
  86. +29 −0 .../node_modules/buster-format/node_modules/buster-core/vendor/buster-util/lib/buster-util/runner.js
Sorry, we could not display the entire diff because too many files (348) changed.
View
64 benchmarks/object.js
@@ -0,0 +1,64 @@
+var Benchmark = new require('benchmark')
+
+var genProp = function(){
+ var o = {}
+ o[Math.random()] = Math.random()
+ return o
+}
+
+var test = function(p, version){
+ var suite = new Benchmark.Suite
+
+ var obj = p.dict({ x: 3 })
+
+ return suite
+
+ .add('set one', function(){
+ p.dict(genProp())
+ })
+
+ .add('set 25', function(){
+ var o = p.dict()
+ for ( var i = 0; i < 25; i +=1 ) {
+ o = o.set(genProp())
+ }
+ })
+
+ .add('set 50', function(){
+ var o = p.dict()
+ for ( var i = 0; i < 50; i +=1 ) {
+ o = o.set(genProp())
+ }
+ })
+
+ .add('set 100', function(){
+ var o = p.dict()
+ for ( var i = 0; i < 100; i +=1 ) {
+ o = o.set(genProp())
+ }
+ })
+
+ .add('set 1000', function(){
+ var o = p.dict()
+ for ( var i = 0; i < 1000; i +=1 ) {
+ o = o.set(genProp())
+ }
+ })
+
+ .add('get one', function(){
+ obj.get('x')
+ })
+
+ .on('complete', function(){
+ var data = this.map(function(o){ return { name: o.name, count: o.count } })
+ console.log('VERSION', version, data)
+ })
+
+ .run({
+ async: true
+ })
+
+}
+
+test(require('../versions/0.7.0'), '0.7.0')
+test(require('../versions/0.6.0'), '0.6.0')
View
22 node_modules/benchmark/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright 2010-2012 Mathias Bynens <http://mathiasbynens.be/>
+Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
+Modified by John-David Dalton <http://allyoucanleet.com/>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
131 node_modules/benchmark/README.md
@@ -0,0 +1,131 @@
+# Benchmark.js <sup>v1.0.0</sup>
+
+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/).
+
+## BestieJS
+
+Benchmark.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.
+
+## Documentation
+
+The documentation for Benchmark.js can be viewed here: <http://benchmarkjs.com/docs>
+
+For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/benchmark.js/wiki/Roadmap).
+
+## Support
+
+Benchmark.js has been tested in at least Adobe AIR 3.1, Chrome 5-21, Firefox 1.5-13, IE 6-9, Opera 9.25-12.01, Safari 3-6, Node.js 0.8.6, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
+
+## Installation and usage
+
+In a browser or Adobe AIR:
+
+~~~ html
+<script src="benchmark.js"></script>
+~~~
+
+Optionally, expose Java’s nanosecond timer by adding the `nano` applet to the `<body>`:
+
+~~~ html
+<applet code="nano" archive="nano.jar"></applet>
+~~~
+
+Or enable Chrome’s microsecond timer by using the [command line switch](http://peter.sh/experiments/chromium-command-line-switches/#enable-benchmarking):
+
+ --enable-benchmarking
+
+Via [npm](http://npmjs.org/):
+
+~~~ bash
+npm install benchmark
+~~~
+
+In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
+
+~~~ js
+var Benchmark = require('benchmark');
+~~~
+
+Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:
+
+~~~ bash
+npm install microtime
+~~~
+
+In [RingoJS v0.7.0-](http://ringojs.org/):
+
+~~~ js
+var Benchmark = require('benchmark').Benchmark;
+~~~
+
+In [Rhino](http://www.mozilla.org/rhino/):
+
+~~~ js
+load('benchmark.js');
+~~~
+
+In an AMD loader like [RequireJS](http://requirejs.org/):
+
+~~~ js
+require({
+ 'paths': {
+ 'benchmark': 'path/to/benchmark'
+ }
+},
+['benchmark'], function(Benchmark) {
+ console.log(Benchmark.version);
+});
+
+// or with platform.js
+// https://github.com/bestiejs/platform.js
+require({
+ 'paths': {
+ 'benchmark': 'path/to/benchmark',
+ 'platform': 'path/to/platform'
+ }
+},
+['benchmark', 'platform'], function(Benchmark, platform) {
+ Benchmark.platform = platform;
+ console.log(Benchmark.platform.name);
+});
+~~~
+
+Usage example:
+
+~~~ js
+var suite = new Benchmark.Suite;
+
+// add tests
+suite.add('RegExp#test', function() {
+ /o/.test('Hello World!');
+})
+.add('String#indexOf', function() {
+ 'Hello World!'.indexOf('o') > -1;
+})
+// add listeners
+.on('cycle', function(event) {
+ console.log(String(event.target));
+})
+.on('complete', function() {
+ console.log('Fastest is ' + this.filter('fastest').pluck('name'));
+})
+// run async
+.run({ 'async': true });
+
+// logs:
+// > RegExp#test x 4,161,532 +-0.99% (59 cycles)
+// > String#indexOf x 6,139,623 +-1.00% (131 cycles)
+// > Fastest is String#indexOf
+~~~
+
+## Authors
+
+* [Mathias Bynens](http://mathiasbynens.be/)
+ [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter")
+* [John-David Dalton](http://allyoucanleet.com/)
+ [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter")
+
+## Contributors
+
+* [Kit Cambridge](http://kitcambridge.github.com/)
+ [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter")
View
3,918 node_modules/benchmark/benchmark.js
3,918 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
2,629 node_modules/benchmark/doc/README.md
2,629 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
62 node_modules/benchmark/package.json
@@ -0,0 +1,62 @@
+{
+ "name": "benchmark",
+ "version": "1.0.0",
+ "description": "A benchmarking library that works on nearly all JavaScript platforms, supports high-resolution timers, and returns statistically significant results.",
+ "homepage": "http://benchmarkjs.com/",
+ "main": "benchmark",
+ "keywords": [
+ "benchmark",
+ "narwhal",
+ "node",
+ "performance",
+ "ringo",
+ "speed"
+ ],
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://mths.be/mit"
+ }
+ ],
+ "author": {
+ "name": "Mathias Bynens",
+ "email": "mathias@benchmarkjs.com",
+ "url": "http://mathiasbynens.be/"
+ },
+ "maintainers": [
+ {
+ "name": "John-David Dalton",
+ "email": "john.david.dalton@gmail.com",
+ "url": "http://allyoucanleet.com/"
+ },
+ {
+ "name": "Mathias Bynens",
+ "email": "mathias@benchmarkjs.com",
+ "url": "http://mathiasbynens.be/"
+ }
+ ],
+ "bugs": {
+ "email": "bugs@benchmarkjs.com",
+ "url": "https://github.com/bestiejs/benchmark.js/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/bestiejs/benchmark.js.git"
+ },
+ "engines": [
+ "node",
+ "rhino"
+ ],
+ "directories": {
+ "doc": "./doc",
+ "test": "./test"
+ },
+ "readme": "# Benchmark.js <sup>v1.0.0</sup>\n\nA [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/).\n\n## BestieJS\n\nBenchmark.js is part of the BestieJS *\"Best in Class\"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.\n\n## Documentation\n\nThe documentation for Benchmark.js can be viewed here: <http://benchmarkjs.com/docs>\n\nFor a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/benchmark.js/wiki/Roadmap).\n\n## Support\n\nBenchmark.js has been tested in at least Adobe AIR 3.1, Chrome 5-21, Firefox 1.5-13, IE 6-9, Opera 9.25-12.01, Safari 3-6, Node.js 0.8.6, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.\n\n## Installation and usage\n\nIn a browser or Adobe AIR:\n\n~~~ html\n<script src=\"benchmark.js\"></script>\n~~~\n\nOptionally, expose Java’s nanosecond timer by adding the `nano` applet to the `<body>`:\n\n~~~ html\n<applet code=\"nano\" archive=\"nano.jar\"></applet>\n~~~\n\nOr enable Chrome’s microsecond timer by using the [command line switch](http://peter.sh/experiments/chromium-command-line-switches/#enable-benchmarking):\n\n --enable-benchmarking\n\nVia [npm](http://npmjs.org/):\n\n~~~ bash\nnpm install benchmark\n~~~\n\nIn [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):\n\n~~~ js\nvar Benchmark = require('benchmark');\n~~~\n\nOptionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:\n\n~~~ bash\nnpm install microtime\n~~~\n\nIn [RingoJS v0.7.0-](http://ringojs.org/):\n\n~~~ js\nvar Benchmark = require('benchmark').Benchmark;\n~~~\n\nIn [Rhino](http://www.mozilla.org/rhino/):\n\n~~~ js\nload('benchmark.js');\n~~~\n\nIn an AMD loader like [RequireJS](http://requirejs.org/):\n\n~~~ js\nrequire({\n 'paths': {\n 'benchmark': 'path/to/benchmark'\n }\n},\n['benchmark'], function(Benchmark) {\n console.log(Benchmark.version);\n});\n\n// or with platform.js\n// https://github.com/bestiejs/platform.js\nrequire({\n 'paths': {\n 'benchmark': 'path/to/benchmark',\n 'platform': 'path/to/platform'\n }\n},\n['benchmark', 'platform'], function(Benchmark, platform) {\n Benchmark.platform = platform;\n console.log(Benchmark.platform.name);\n});\n~~~\n\nUsage example:\n\n~~~ js\nvar suite = new Benchmark.Suite;\n\n// add tests\nsuite.add('RegExp#test', function() {\n /o/.test('Hello World!');\n})\n.add('String#indexOf', function() {\n 'Hello World!'.indexOf('o') > -1;\n})\n// add listeners\n.on('cycle', function(event) {\n console.log(String(event.target));\n})\n.on('complete', function() {\n console.log('Fastest is ' + this.filter('fastest').pluck('name'));\n})\n// run async\n.run({ 'async': true });\n\n// logs:\n// > RegExp#test x 4,161,532 +-0.99% (59 cycles)\n// > String#indexOf x 6,139,623 +-1.00% (131 cycles)\n// > Fastest is String#indexOf\n~~~\n\n## Authors\n\n* [Mathias Bynens](http://mathiasbynens.be/)\n [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias \"Follow @mathias on Twitter\")\n* [John-David Dalton](http://allyoucanleet.com/)\n [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton \"Follow @jdalton on Twitter\")\n\n## Contributors\n\n* [Kit Cambridge](http://kitcambridge.github.com/)\n [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge \"Follow @kitcambridge on Twitter\")\n",
+ "readmeFilename": "README.md",
+ "_id": "benchmark@1.0.0",
+ "dist": {
+ "shasum": "5dbb045cc5636347e0c48e8bff1612bba783eefa"
+ },
+ "_from": "benchmark@1.0.0",
+ "_resolved": "https://registry.npmjs.org/benchmark/-/benchmark-1.0.0.tgz"
+}
View
9 node_modules/benchmark/test/run-test.sh
@@ -0,0 +1,9 @@
+cd "$(dirname "$0")"
+for cmd in rhino ringo narwhal node; do
+ echo ""
+ echo "Testing in $cmd..."
+ $cmd test.js
+done
+echo ""
+echo "Testing in a browser..."
+open index.html
View
2,074 node_modules/benchmark/test/test.js
2,074 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
1 node_modules/multimethod/.npmignore
@@ -0,0 +1 @@
+node_modules/
View
22 node_modules/multimethod/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2011 Kris Jordan
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
View
154 node_modules/multimethod/README.md
@@ -0,0 +1,154 @@
+# Motivation
+
+Multimethods are a functional programming control structure for dispatching
+function calls with user-defined criteria that can be changed at run time.
+Inspired by clojure's multimethods, multimethod.js provides an alternative to
+classical, prototype-chain based polymorphism.
+
+# Installation
+
+Install with `npm` for use in node.js based projects.
+
+ npm install multimethod
+ node
+ > require('multimethod')
+
+For in-browser use you will need to grab
+[underscore.js](http://documentcloud.github.com/underscore/) and multimethod.js:
+
+- underscore.js
+ - Development: http://documentcloud.github.com/underscore/underscore.js
+ - Minified: http://documentcloud.github.com/underscore/underscore-min.js
+- multimethod.js
+ - Development: https://raw.github.com/KrisJordan/multimethod-js/master/multimethod.js
+ - Minified: https://raw.github.com/KrisJordan/multimethod-js/master/multimethod-min.js
+
+# API
+
+- Constructor: `multimethod`( [fn | string] ): If empty, identity dispatch
+ function used, otherwise same as `dispatch`.
+- `dispatch`(fn | string): Sets the multimethod's dispatch function. String
+ values are transformed into a pluck function which projects a single
+ property from an object argument.
+- `when`(match, fn | value): Add a `method` to be called when the dispatched
+ value matches 'match'. If a non-function value is provided it will be used.
+ Using the same match value twice will override previously set match value
+ and method.
+- `remove`(match): Remove a method/match pair.
+- `default`(fn | value): Catch-all case when no other matched method is found.
+
+# Usage
+
+## The Basics
+
+A `multimethod` is instantiated with the `multimethod` function.
+
+ var stopLightColor = multimethod();
+
+A `multimethod` has methods. A `method` is has two parts, its match value
+and its implementation function. Methods are added using `when`.
+
+ stopLightColor.when("go", function() { return "green"; })
+ .when("stop", function() { return "red"; });
+
+You can call a `multimethod` just like any other function.
+
+ var goColor = stopLightColor("go");
+ console.log(goColor); // prints "green"
+
+When no method matches a `multimethod` it can take action with a `default` method.
+
+ stopLightColor.default( function() { return "unknown"; } );
+ console.log( stopLightColor("yield") ); // prints "unknown"
+
+Unlike `switch` statements, a `multimethod` can handle new cases at run time.
+
+ stopLightColor.when("yield", function() { return "yellow"; });
+
+There is a shorter way for a `method` to return a simple value. Rather than
+passing an implementation function to `when`, provide the value.
+
+ stopLightColor.when("yield", "yellow");
+ console.log( stopLightColor("yield") ); // prints "yellow"
+
+A `method` can be removed at run time.
+
+ stopLightColor.remove("go");
+ console.log( stopLightColor("go") ); // prints "unknown"
+
+## Deep Equality Matching
+
+Method match values are compared using the underscore.js
+[`isEqual`](http://documentcloud.github.com/underscore/#isEqual)
+function. Deep equality testing allows great expressivity than a native
+`switch` statement.
+
+ var greatPairs = multimethod()
+ .when( ["Salt", "Pepper"], "Shakers" )
+ .when( [{"name":"Bonnie"}, {"name":"Clyde"}], "Robbers" );
+
+ console.log( greatPairs( ["Salt", "Pepper"] ) ); // Shakers
+
+## Dispatch Function
+
+Each `multimethod` uses a `dispatch` function to select the
+`method` to call. The `dispatch` function is passed the arguments
+the `multimethod` is invoked with and returns a value to match
+with a `method`.
+
+The default `dispatch` function is an identity function.
+The basic `stopLightColor` examples could have been
+created with an explicit `dispatch` function.
+
+ var stopLightColor = multimethod()
+ .dispatch(function(state){
+ return state;
+ })
+ .when('go', 'green');
+ console.log( stopLightColor('go') ); // green
+
+The power of the `multimethod` paradigm is the ability to dispatch with a
+user-defined function. This gives a `multimethod` its "polymorphic" powers.
+Unlike classical, object-oriented polymorphism where the compiler dispatches
+based on the type hierarchy, a `multimethod` can dispatch on any criteria.
+
+ var contacts = [
+ {"name":"Jack", "service":"Twitter","handle": "@jack"},
+ {"name":"Diane","service":"Email", "address":"d@g.com"},
+ {"name":"John", "service":"Phone", "number": "919-919-9191"}
+ ];
+
+ var sendMessage = multimethod()
+ .dispatch(function(contact, msg) {
+ return contact.service;
+ })
+ .when("Twitter", function(contact, msg) {
+ console.log("Tweet @"+contact.handle+":"+msg);
+ })
+ .when("Email", function(contact, msg) {
+ console.log("Emailing "+contact.address+":"+msg);
+ })
+ .default(function(contact, msg) {
+ console.log("Could not message " + contact.name);
+ });
+
+ // Blast a message
+ contacts.forEach( function(contact) {
+ sendMessage(contact, "Hello, world.");
+ });
+
+Plucking a single property from an object is so commonly used as a `dispatch`
+function, like in the example above, there is a shortcut for this pattern.
+The following `dispatch` call is equivalent to above.
+
+ sendMessage.dispatch( 'service' );
+
+A `multimethod`'s `dispatch` is usually specified when constructed.
+
+ var sendMessage = multimethod('service');
+
+Just like `method`s can be added and removed from a `multimethod` at
+run time, the `dispatch` function can also be redefined at run time.
+Ponder the implications of that for a minute. It is really powerful and
+really dangerous. Don't shoot your eye out.
+
View
19 node_modules/multimethod/Rakefile
@@ -0,0 +1,19 @@
+require 'rubygems'
+require 'closure-compiler'
+
+HEADER = /((^\s*\/\/.*\n)+)/
+
+desc "Use the Closure Compiler to compress multimethod.js"
+task :build do
+ source = File.read('multimethod.js')
+ header = source.match(HEADER)
+ min = Closure::Compiler.new.compress(source)
+ File.open('multimethod-min.js', 'w') do |file|
+ file.write header[1].squeeze(' ') + min
+ end
+end
+
+desc "Build the docco documentation"
+task :doc do
+ sh "docco multimethod.js"
+end
View
186 node_modules/multimethod/docs/docco.css
@@ -0,0 +1,186 @@
+/*--------------------- Layout and Typography ----------------------------*/
+body {
+ font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
+ font-size: 15px;
+ line-height: 22px;
+ color: #252519;
+ margin: 0; padding: 0;
+}
+a {
+ color: #261a3b;
+}
+ a:visited {
+ color: #261a3b;
+ }
+p {
+ margin: 0 0 15px 0;
+}
+h1, h2, h3, h4, h5, h6 {
+ margin: 0px 0 15px 0;
+}
+ h1 {
+ margin-top: 40px;
+ }
+#container {
+ position: relative;
+}
+#background {
+ position: fixed;
+ top: 0; left: 525px; right: 0; bottom: 0;
+ background: #f5f5ff;
+ border-left: 1px solid #e5e5ee;
+ z-index: -1;
+}
+#jump_to, #jump_page {
+ background: white;
+ -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
+ -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
+ font: 10px Arial;
+ text-transform: uppercase;
+ cursor: pointer;
+ text-align: right;
+}
+#jump_to, #jump_wrapper {
+ position: fixed;
+ right: 0; top: 0;
+ padding: 5px 10px;
+}
+ #jump_wrapper {
+ padding: 0;
+ display: none;
+ }
+ #jump_to:hover #jump_wrapper {
+ display: block;
+ }
+ #jump_page {
+ padding: 5px 0 3px;
+ margin: 0 0 25px 25px;
+ }
+ #jump_page .source {
+ display: block;
+ padding: 5px 10px;
+ text-decoration: none;
+ border-top: 1px solid #eee;
+ }
+ #jump_page .source:hover {
+ background: #f5f5ff;
+ }
+ #jump_page .source:first-child {
+ }
+table td {
+ border: 0;
+ outline: 0;
+}
+ td.docs, th.docs {
+ max-width: 450px;
+ min-width: 450px;
+ min-height: 5px;
+ padding: 10px 25px 1px 50px;
+ overflow-x: hidden;
+ vertical-align: top;
+ text-align: left;
+ }
+ .docs pre {
+ margin: 15px 0 15px;
+ padding-left: 15px;
+ }
+ .docs p tt, .docs p code {
+ background: #f8f8ff;
+ border: 1px solid #dedede;
+ font-size: 12px;
+ padding: 0 0.2em;
+ }
+ .pilwrap {
+ position: relative;
+ }
+ .pilcrow {
+ font: 12px Arial;
+ text-decoration: none;
+ color: #454545;
+ position: absolute;
+ top: 3px; left: -20px;
+ padding: 1px 2px;
+ opacity: 0;
+ -webkit-transition: opacity 0.2s linear;
+ }
+ td.docs:hover .pilcrow {
+ opacity: 1;
+ }
+ td.code, th.code {
+ padding: 14px 15px 16px 25px;
+ width: 100%;
+ vertical-align: top;
+ background: #f5f5ff;
+ border-left: 1px solid #e5e5ee;
+ }
+ pre, tt, code {
+ font-size: 12px; line-height: 18px;
+ font-family: Monaco, Consolas, "Lucida Console", monospace;
+ margin: 0; padding: 0;
+ }
+
+
+/*---------------------- Syntax Highlighting -----------------------------*/
+td.linenos { background-color: #f0f0f0; padding-right: 10px; }
+span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
+body .hll { background-color: #ffffcc }
+body .c { color: #408080; font-style: italic } /* Comment */
+body .err { border: 1px solid #FF0000 } /* Error */
+body .k { color: #954121 } /* Keyword */
+body .o { color: #666666 } /* Operator */
+body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+body .cp { color: #BC7A00 } /* Comment.Preproc */
+body .c1 { color: #408080; font-style: italic } /* Comment.Single */
+body .cs { color: #408080; font-style: italic } /* Comment.Special */
+body .gd { color: #A00000 } /* Generic.Deleted */
+body .ge { font-style: italic } /* Generic.Emph */
+body .gr { color: #FF0000 } /* Generic.Error */
+body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+body .gi { color: #00A000 } /* Generic.Inserted */
+body .go { color: #808080 } /* Generic.Output */
+body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+body .gs { font-weight: bold } /* Generic.Strong */
+body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+body .gt { color: #0040D0 } /* Generic.Traceback */
+body .kc { color: #954121 } /* Keyword.Constant */
+body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */
+body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */
+body .kp { color: #954121 } /* Keyword.Pseudo */
+body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */
+body .kt { color: #B00040 } /* Keyword.Type */
+body .m { color: #666666 } /* Literal.Number */
+body .s { color: #219161 } /* Literal.String */
+body .na { color: #7D9029 } /* Name.Attribute */
+body .nb { color: #954121 } /* Name.Builtin */
+body .nc { color: #0000FF; font-weight: bold } /* Name.Class */
+body .no { color: #880000 } /* Name.Constant */
+body .nd { color: #AA22FF } /* Name.Decorator */
+body .ni { color: #999999; font-weight: bold } /* Name.Entity */
+body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+body .nf { color: #0000FF } /* Name.Function */
+body .nl { color: #A0A000 } /* Name.Label */
+body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+body .nt { color: #954121; font-weight: bold } /* Name.Tag */
+body .nv { color: #19469D } /* Name.Variable */
+body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+body .w { color: #bbbbbb } /* Text.Whitespace */
+body .mf { color: #666666 } /* Literal.Number.Float */
+body .mh { color: #666666 } /* Literal.Number.Hex */
+body .mi { color: #666666 } /* Literal.Number.Integer */
+body .mo { color: #666666 } /* Literal.Number.Oct */
+body .sb { color: #219161 } /* Literal.String.Backtick */
+body .sc { color: #219161 } /* Literal.String.Char */
+body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
+body .s2 { color: #219161 } /* Literal.String.Double */
+body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+body .sh { color: #219161 } /* Literal.String.Heredoc */
+body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+body .sx { color: #954121 } /* Literal.String.Other */
+body .sr { color: #BB6688 } /* Literal.String.Regex */
+body .s1 { color: #219161 } /* Literal.String.Single */
+body .ss { color: #19469D } /* Literal.String.Symbol */
+body .bp { color: #954121 } /* Name.Builtin.Pseudo */
+body .vc { color: #19469D } /* Name.Variable.Class */
+body .vg { color: #19469D } /* Name.Variable.Global */
+body .vi { color: #19469D } /* Name.Variable.Instance */
+body .il { color: #666666 } /* Literal.Number.Integer.Long */
View
116 node_modules/multimethod/docs/multimethod.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html> <html> <head> <title>multimethod.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> multimethod.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>multimethod.js 0.1.0</p>
+
+<p>(c) 2011 Kris Jordan</p>
+
+<p><code>multimethod</code> is freely distributable under the MIT license.
+For details and documentation:
+<a href="http://krisjordan.com/multimethod-js">http://krisjordan.com/multimethod-js</a></p> </td> <td class="code"> <div class="highlight"><pre><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>Multimethods are a functional programming control structure for dispatching
+function calls with user-defined criteria that can be changed at run time.
+Inspired by clojure's multimethods, multimethod.js provides an alternative to
+classical, prototype-chain based polymorphism.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <h2>Internal Utility Functions</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>No operation function used by default by <code>default</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">noop</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{};</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Identity <code>dispatch</code> function. Default value of <code>dispatch</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">identity</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">a</span><span class="p">;</span> <span class="p">};</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>A <code>method</code> in <code>multimethod</code> is a (match value, function) pair stored in
+an array. <code>indexOf</code> takes a value and array of methods and returns the
+index of the method whose value is equal to the first argument. If no
+match is found, false is returned.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">indexOf</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">methods</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">methods</span><span class="p">)</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">matches</span> <span class="o">=</span> <span class="nx">methods</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
+ <span class="k">if</span><span class="p">(</span><span class="nx">_</span><span class="p">(</span><span class="nx">value</span><span class="p">).</span><span class="nx">isEqual</span><span class="p">(</span><span class="nx">matches</span><span class="p">))</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="nx">i</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="p">}</span>
+ <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
+ <span class="p">}</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Given a dispatch <code>value</code> and array of <code>method</code>s, return the function
+of the <code>method</code> whose match value corresponds to a dispatch value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">match</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">methods</span><span class="p">)</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="nx">indexOf</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">methods</span><span class="p">);</span>
+ <span class="k">if</span><span class="p">(</span><span class="nx">index</span> <span class="o">!==</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="nx">methods</span><span class="p">[</span><span class="nx">index</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
+ <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="p">}</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Simple, consistent helper that returns a native value or invokes a function
+and returns its return value. Used by <code>when</code> and <code>default</code> allowing
+short-hand notation for returning values rather than calling functions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">toValue</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">subject</span><span class="p">,</span> <span class="nx">args</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">if</span><span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isFunction</span><span class="p">(</span><span class="nx">subject</span><span class="p">))</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="nx">subject</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">args</span><span class="p">);</span>
+ <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="nx">subject</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>Plucking a single property value from an object in <code>dispatch</code> is commonly
+used. The internal <code>pluck</code> function returns a function suitable for use
+by <code>dispatch</code> for just that purpose.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">pluck</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">property</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">object</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="nx">object</span><span class="p">[</span><span class="nx">property</span><span class="p">];</span>
+ <span class="p">}</span>
+ <span class="p">};</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <h2>Implementation</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p><code>multimethod</code> is a higher-order function that returns a closure with
+methods to control its behavior.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">multimethod</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">dispatch</span><span class="p">)</span> <span class="p">{</span> </pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <h3>Private Properties</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p><code>_dispatch</code> holds either a dispatch function or a string
+corresponding to the property name whose value will be plucked
+and used as the <code>dispatch</code> criteria.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">_dispatch</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p><code>_methods</code> is a an array of <code>method</code> arrays. A <code>method</code> is
+[ matchValue, implementation ].</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_methods</span> <span class="o">=</span> <span class="p">[],</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p><code>_default</code> is the fallback method when a <code>multimethod</code> is called
+and matches no other method.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_default</span> <span class="o">=</span> <span class="nx">noop</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>The fundamental control flow of the <code>multimethod</code> is implemented
+in <code>_lookup</code>. First we invoke the dispatch function, this gives
+us our match criteria. Then we match a method based on the criteria
+or return the default method.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">_lookup</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">criteria</span> <span class="o">=</span> <span class="nx">_dispatch</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">),</span>
+ <span class="nx">method</span> <span class="o">=</span> <span class="nx">match</span><span class="p">(</span><span class="nx">criteria</span><span class="p">,</span> <span class="nx">_methods</span><span class="p">);</span>
+ <span class="k">if</span><span class="p">(</span><span class="nx">method</span> <span class="o">!==</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="nx">method</span><span class="p">;</span>
+ <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="nx">_default</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="p">};</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>The result of calling <code>multimethod</code>'s "factory" function is this function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">returnFn</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">method</span> <span class="o">=</span> <span class="nx">_lookup</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">);</span>
+ <span class="k">return</span> <span class="nx">toValue</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">method</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">);</span>
+ <span class="p">};</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <h3>Member Methods / API</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p><code>dispatch</code> is the accessor to the <code>multimethod</code>'s <code>_dispatch</code> function.
+When called with a string we create an anonymous pluck function as a
+shorthand.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">returnFn</span><span class="p">[</span><span class="s1">&#39;dispatch&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">dispatch</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">if</span><span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isFunction</span><span class="p">(</span><span class="nx">dispatch</span><span class="p">))</span> <span class="p">{</span>
+ <span class="nx">_dispatch</span> <span class="o">=</span> <span class="nx">dispatch</span><span class="p">;</span>
+ <span class="p">}</span> <span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nx">_</span><span class="p">.</span><span class="nx">isString</span><span class="p">(</span><span class="nx">dispatch</span><span class="p">))</span> <span class="p">{</span>
+ <span class="nx">_dispatch</span> <span class="o">=</span> <span class="nx">pluck</span><span class="p">(</span><span class="nx">dispatch</span><span class="p">);</span>
+ <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+ <span class="k">throw</span> <span class="s2">&quot;dispatch requires a function or a string.&quot;</span><span class="p">;</span>
+ <span class="p">}</span>
+ <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
+ <span class="p">}</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>If <code>multimethod</code> is called/"constructed" with a <code>dispatch</code> value we go ahead and set
+it up here. Otherwise <code>dispatch</code> is the <code>identity</code> function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">returnFn</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">dispatch</span> <span class="o">||</span> <span class="nx">identity</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p><code>when</code> introduces new <code>method</code>s to a <code>multimethod</code>. If the
+<code>matchValue</code> has already been registered the new method will
+overwrite the old method.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">returnFn</span><span class="p">[</span><span class="s1">&#39;when&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">matchValue</span><span class="p">,</span> <span class="nx">fn</span><span class="p">)</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="nx">indexOf</span><span class="p">(</span><span class="nx">matchValue</span><span class="p">,</span> <span class="nx">_methods</span><span class="p">);</span>
+ <span class="k">if</span><span class="p">(</span><span class="nx">index</span> <span class="o">!==</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">_methods</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">matchValue</span><span class="p">,</span> <span class="nx">fn</span><span class="p">];</span>
+ <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+ <span class="nx">_methods</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="nx">matchValue</span><span class="p">,</span> <span class="nx">fn</span><span class="p">]);</span>
+ <span class="p">}</span>
+ <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
+ <span class="p">}</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p><code>remove</code> will unregister a <code>method</code> based on matchValue</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">returnFn</span><span class="p">[</span><span class="s1">&#39;remove&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">matchValue</span><span class="p">)</span> <span class="p">{</span>
+ <span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="nx">indexOf</span><span class="p">(</span><span class="nx">matchValue</span><span class="p">,</span> <span class="nx">_methods</span><span class="p">);</span>
+ <span class="k">if</span><span class="p">(</span><span class="nx">index</span> <span class="o">!==</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">_methods</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
+ <span class="p">}</span>
+ <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
+ <span class="p">}</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p><code>default</code> is an accessor to control the <code>_default</code>, fallback method
+that is called when no match is found when the <code>multimethod</code> is
+invoked and dispatched.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">returnFn</span><span class="p">[</span><span class="s1">&#39;default&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">method</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">_default</span> <span class="o">=</span> <span class="nx">method</span><span class="p">;</span>
+ <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
+ <span class="p">}</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">&#182;</a> </div> <p>Our <code>multimethod</code> instance/closure is fully setup now, return!</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="nx">returnFn</span><span class="p">;</span>
+ <span class="p">};</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>The following snippet courtesy of underscore.js.
+Export <code>multimethod</code> to the window/exports namespace.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">exports</span> <span class="o">!==</span> <span class="s1">&#39;undefined&#39;</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">module</span> <span class="o">!==</span> <span class="s1">&#39;undefined&#39;</span> <span class="o">&amp;&amp;</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">exports</span> <span class="o">=</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nx">multimethod</span><span class="p">;</span>
+ <span class="kd">var</span> <span class="nx">_</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;underscore&#39;</span><span class="p">);</span>
+ <span class="p">}</span>
+ <span class="nx">exports</span><span class="p">.</span><span class="nx">multimethod</span> <span class="o">=</span> <span class="nx">multimethod</span><span class="p">;</span>
+ <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">define</span> <span class="o">===</span> <span class="s1">&#39;function&#39;</span> <span class="o">&amp;&amp;</span> <span class="nx">define</span><span class="p">.</span><span class="nx">amd</span><span class="p">)</span> <span class="p">{</span>
+ <span class="nx">define</span><span class="p">(</span><span class="s1">&#39;multimethod&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="nx">multimethod</span><span class="p">;</span>
+ <span class="p">});</span>
+ <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+ <span class="k">this</span><span class="p">[</span><span class="s1">&#39;multimethod&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nx">multimethod</span><span class="p">;</span>
+ <span class="kd">var</span> <span class="nx">_</span> <span class="o">=</span> <span class="k">this</span><span class="p">[</span><span class="s1">&#39;_&#39;</span><span class="p">];</span>
+ <span class="p">}</span>
+
+ <span class="nx">multimethod</span><span class="p">.</span><span class="nx">version</span> <span class="o">=</span> <span class="s1">&#39;0.1.0&#39;</span><span class="p">;</span>
+
+<span class="p">}).</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
+
+</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
View
1 node_modules/multimethod/index.js
@@ -0,0 +1 @@
+module.exports = require('./multimethod');
View
10 node_modules/multimethod/multimethod-min.js
@@ -0,0 +1,10 @@
+// multimethod.js 0.1.0
+//
+// (c) 2011 Kris Jordan
+//
+// Multimethod is freely distributable under the MIT license.
+// For details and documentation:
+// [http://krisjordan.com/multimethod-js](http://krisjordan.com/multimethod-js)
+(function(){var j=function(){},k=function(g){return g},h=function(g,c){for(var d in c){var b=c[d][0];if(f(g).isEqual(b))return d}return false},l=function(b){return function(c){return c[b]}},b=function(b){var c,d=[],i=j,m=function(){var a=c.apply(this,arguments),a=h(a,d),a=a!==false?d[a][1]:false;return a!==false?a:i},e=function(){var a=m.apply(this,arguments);return f.isFunction(a)?a.apply(this,arguments):a};e.dispatch=function(a){if(f.isFunction(a))c=a;else if(f.isString(a))c=l(a);else throw"dispatch requires a function or a string.";
+return this};e.dispatch(b||k);e.when=function(a,b){var c=h(a,d);c!==false?d[c]=[a,b]:d.push([a,b]);return this};e.remove=function(a){a=h(a,d);a!==false&&d.splice(a,1);return this};e["default"]=function(a){i=a;return this};return e};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports){exports=module.exports=b;var f=require("underscore")}exports.multimethod=b}else typeof define==="function"&&define.amd?define("multimethod",function(){return b}):(this.multimethod=b,f=this._);
+b.version="0.1.0"}).call(this);
View
181 node_modules/multimethod/multimethod.js
@@ -0,0 +1,181 @@
+// multimethod.js 0.1.0
+//
+// (c) 2011 Kris Jordan
+//
+// `multimethod` is freely distributable under the MIT license.
+// For details and documentation:
+// [http://krisjordan.com/multimethod-js](http://krisjordan.com/multimethod-js)
+
+(function() {
+
+ // Multimethods are a functional programming control structure for dispatching
+ // function calls with user-defined criteria that can be changed at run time.
+ // Inspired by clojure's multimethods, multimethod.js provides an alternative to
+ // classical, prototype-chain based polymorphism.
+
+ // ## Internal Utility Functions
+
+ // No operation function used by default by `default`.
+ var noop = function() {};
+
+ // Identity `dispatch` function. Default value of `dispatch`.
+ var identity = function(a) { return a; };
+
+ // A `method` in `multimethod` is a (match value, function) pair stored in
+ // an array. `indexOf` takes a value and array of methods and returns the
+ // index of the method whose value is equal to the first argument. If no
+ // match is found, false is returned.
+ var indexOf = function(value, methods) {
+ for(var i in methods) {
+ var matches = methods[i][0];
+ if(_(value).isEqual(matches)) {
+ return i;
+ }
+ }
+ return false;
+ }
+
+ // Given a dispatch `value` and array of `method`s, return the function
+ // of the `method` whose match value corresponds to a dispatch value.
+ var match = function(value, methods) {
+ var index = indexOf(value, methods);
+ if(index !== false) {
+ return methods[index][1];
+ } else {
+ return false;
+ }
+ }
+
+ // Simple, consistent helper that returns a native value or invokes a function
+ // and returns its return value. Used by `when` and `default` allowing
+ // short-hand notation for returning values rather than calling functions.
+ var toValue = function(subject, args) {
+ if(_.isFunction(subject)) {
+ return subject.apply(this, args);
+ } else {
+ return subject;
+ }
+ };
+
+ // Plucking a single property value from an object in `dispatch` is commonly
+ // used. The internal `pluck` function returns a function suitable for use
+ // by `dispatch` for just that purpose.
+ var pluck = function(property) {
+ return function(object) {
+ return object[property];
+ }
+ };
+
+
+ // ## Implementation
+
+ // `multimethod` is a higher-order function that returns a closure with
+ // methods to control its behavior.
+ var multimethod = function(dispatch) {
+
+ // ### Private Properties
+
+ // `_dispatch` holds either a dispatch function or a string
+ // corresponding to the property name whose value will be plucked
+ // and used as the `dispatch` criteria.
+ var _dispatch,
+ // `_methods` is a an array of `method` arrays. A `method` is
+ // [ matchValue, implementation ].
+ _methods = [],
+ // `_default` is the fallback method when a `multimethod` is called
+ // and matches no other method.
+ _default = noop;
+
+ // The fundamental control flow of the `multimethod` is implemented
+ // in `_lookup`. First we invoke the dispatch function, this gives
+ // us our match criteria. Then we match a method based on the criteria
+ // or return the default method.
+ var _lookup = function() {
+ var criteria = _dispatch.apply(this, arguments),
+ method = match(criteria, _methods);
+ if(method !== false) {
+ return method;
+ } else {
+ return _default;
+ }
+ };
+
+ // The result of calling `multimethod`'s "factory" function is this function.
+ var returnFn = function() {
+ var method = _lookup.apply(this, arguments);
+ return toValue.call(this, method, arguments);
+ };
+
+ // ### Member Methods / API
+
+ // `dispatch` is the accessor to the `multimethod`'s `_dispatch` function.
+ // When called with a string we create an anonymous pluck function as a
+ // shorthand.
+ returnFn['dispatch'] = function(dispatch) {
+ if(_.isFunction(dispatch)) {
+ _dispatch = dispatch;
+ } else if(_.isString(dispatch)) {
+ _dispatch = pluck(dispatch);
+ } else {
+ throw "dispatch requires a function or a string.";
+ }
+ return this;
+ }
+ // If `multimethod` is called/"constructed" with a `dispatch` value we go ahead and set
+ // it up here. Otherwise `dispatch` is the `identity` function.
+ returnFn.dispatch(dispatch || identity);
+
+ // `when` introduces new `method`s to a `multimethod`. If the
+ // `matchValue` has already been registered the new method will
+ // overwrite the old method.
+ returnFn['when'] = function(matchValue, fn) {
+ var index = indexOf(matchValue, _methods);
+ if(index !== false) {
+ _methods[index] = [matchValue, fn];
+ } else {
+ _methods.push([matchValue, fn]);
+ }
+ return this;
+ }
+
+ // `remove` will unregister a `method` based on matchValue
+ returnFn['remove'] = function(matchValue) {
+ var index = indexOf(matchValue, _methods);
+ if(index !== false) {
+ _methods.splice(index, 1);
+ }
+ return this;
+ }
+
+ // `default` is an accessor to control the `_default`, fallback method
+ // that is called when no match is found when the `multimethod` is
+ // invoked and dispatched.
+ returnFn['default'] = function(method) {
+ _default = method;
+ return this;
+ }
+
+ // Our `multimethod` instance/closure is fully setup now, return!
+ return returnFn;
+ };
+
+ // The following snippet courtesy of underscore.js.
+ // Export `multimethod` to the window/exports namespace.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = multimethod;
+ var _ = require('underscore');
+ }
+ exports.multimethod = multimethod;
+ } else if (typeof define === 'function' && define.amd) {
+ define('multimethod', function() {
+ return multimethod;
+ });
+ } else {
+ this['multimethod'] = multimethod;
+ var _ = this['_'];
+ }
+
+ multimethod.version = '0.1.0';
+
+}).call(this);
View
3 node_modules/multimethod/node_modules/underscore/.npmignore
@@ -0,0 +1,3 @@
+test/
+Rakefile
+docs/
View
22 node_modules/multimethod/node_modules/underscore/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2011 Jeremy Ashkenas, DocumentCloud
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
View
19 node_modules/multimethod/node_modules/underscore/README
@@ -0,0 +1,19 @@
+ __
+ /\ \ __
+ __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____
+/\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\
+\ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\
+ \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
+ \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/
+ \ \____/
+ \/___/
+
+Underscore is a utility-belt library for JavaScript that provides
+support for the usual functional suspects (each, map, reduce, filter...)
+without extending any core JavaScript objects.
+
+For Docs, License, Tests, and pre-packed downloads, see:
+http://documentcloud.github.com/underscore/
+
+Many thanks to our contributors:
+https://github.com/documentcloud/underscore/contributors
View
1,726 node_modules/multimethod/node_modules/underscore/index.html
1,726 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
1 node_modules/multimethod/node_modules/underscore/index.js
@@ -0,0 +1 @@
+module.exports = require('./underscore');
View
32 node_modules/multimethod/node_modules/underscore/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "underscore",
+ "description": "JavaScript's functional programming helper library.",
+ "homepage": "http://documentcloud.github.com/underscore/",
+ "keywords": [
+ "util",
+ "functional",
+ "server",
+ "client",
+ "browser"
+ ],
+ "author": {
+ "name": "Jeremy Ashkenas",
+ "email": "jeremy@documentcloud.org"
+ },
+ "contributors": [],
+ "dependencies": {},
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/documentcloud/underscore.git"
+ },
+ "main": "underscore.js",
+ "version": "1.2.1",
+ "readme": " __ \n /\\ \\ __ \n __ __ ___ \\_\\ \\ __ _ __ ____ ___ ___ _ __ __ /\\_\\ ____ \n/\\ \\/\\ \\ /' _ `\\ /'_ \\ /'__`\\/\\ __\\/ ,__\\ / ___\\ / __`\\/\\ __\\/'__`\\ \\/\\ \\ /',__\\ \n\\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\/\\ __/\\ \\ \\//\\__, `\\/\\ \\__//\\ \\ \\ \\ \\ \\//\\ __/ __ \\ \\ \\/\\__, `\\\n \\ \\____/\\ \\_\\ \\_\\ \\___,_\\ \\____\\\\ \\_\\\\/\\____/\\ \\____\\ \\____/\\ \\_\\\\ \\____\\/\\_\\ _\\ \\ \\/\\____/\n \\/___/ \\/_/\\/_/\\/__,_ /\\/____/ \\/_/ \\/___/ \\/____/\\/___/ \\/_/ \\/____/\\/_//\\ \\_\\ \\/___/ \n \\ \\____/ \n \\/___/\n\nUnderscore is a utility-belt library for JavaScript that provides \nsupport for the usual functional suspects (each, map, reduce, filter...) \nwithout extending any core JavaScript objects.\n\nFor Docs, License, Tests, and pre-packed downloads, see:\nhttp://documentcloud.github.com/underscore/\n\nMany thanks to our contributors:\nhttps://github.com/documentcloud/underscore/contributors\n",
+ "readmeFilename": "README",
+ "_id": "underscore@1.2.1",
+ "dist": {
+ "shasum": "1bb0ecefbe85e8f44b2b3a4e18d3e8bb0b9a3cef"
+ },
+ "_from": "underscore@1.2.1",
+ "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.2.1.tgz"
+}
View
30 node_modules/multimethod/node_modules/underscore/underscore-min.js
@@ -0,0 +1,30 @@
+// Underscore.js 1.2.1
+// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the MIT license.
+// Portions of Underscore are inspired or borrowed from Prototype,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
+(function(){function u(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(b.isFunction(a.isEqual))return a.isEqual(c);if(b.isFunction(c.isEqual))return c.isEqual(a);var e=typeof a;if(e!=typeof c)return false;if(!a!=!c)return false;if(b.isNaN(a))return b.isNaN(c);var g=b.isString(a),f=b.isString(c);if(g||f)return g&&f&&String(a)==String(c);g=b.isNumber(a);f=b.isNumber(c);if(g||f)return g&&f&&+a==+c;g=b.isBoolean(a);f=b.isBoolean(c);
+if(g||f)return g&&f&&+a==+c;g=b.isDate(a);f=b.isDate(c);if(g||f)return g&&f&&a.getTime()==c.getTime();g=b.isRegExp(a);f=b.isRegExp(c);if(g||f)return g&&f&&a.source==c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase;if(e!="object")return false;if(a.length!==c.length)return false;if(a.constructor!==c.constructor)return false;for(e=d.length;e--;)if(d[e]==a)return true;d.push(a);var e=0,g=true,h;for(h in a)if(m.call(a,h)&&(e++,!(g=m.call(c,h)&&u(a[h],c[h],d))))break;if(g){for(h in c)if(m.call(c,
+h)&&!e--)break;g=!e}d.pop();return g}var r=this,F=r._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,G=k.unshift,l=p.toString,m=p.hasOwnProperty,v=k.forEach,w=k.map,x=k.reduce,y=k.reduceRight,z=k.filter,A=k.every,B=k.some,q=k.indexOf,C=k.lastIndexOf,p=Array.isArray,H=Object.keys,s=Function.prototype.bind,b=function(a){return new n(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else typeof define==="function"&&define.amd?
+define("underscore",function(){return b}):r._=b;b.VERSION="1.2.1";var j=b.each=b.forEach=function(a,c,b){if(a!=null)if(v&&a.forEach===v)a.forEach(c,b);else if(a.length===+a.length)for(var e=0,g=a.length;e<g;e++){if(e in a&&c.call(b,a[e],e,a)===o)break}else for(e in a)if(m.call(a,e)&&c.call(b,a[e],e,a)===o)break};b.map=function(a,c,b){var e=[];if(a==null)return e;if(w&&a.map===w)return a.map(c,b);j(a,function(a,f,h){e[e.length]=c.call(b,a,f,h)});return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var g=
+d!==void 0;a==null&&(a=[]);if(x&&a.reduce===x)return e&&(c=b.bind(c,e)),g?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){g?d=c.call(e,d,a,b,i):(d=a,g=true)});if(!g)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){a==null&&(a=[]);if(y&&a.reduceRight===y)return e&&(c=b.bind(c,e)),d!==void 0?a.reduceRight(c,d):a.reduceRight(c);a=(b.isArray(a)?a.slice():b.toArray(a)).reverse();return b.reduce(a,c,d,e)};b.find=b.detect=function(a,c,b){var e;
+D(a,function(a,f,h){if(c.call(b,a,f,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.filter===z)return a.filter(c,b);j(a,function(a,f,h){c.call(b,a,f,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,f,h){c.call(b,a,f,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(A&&a.every===A)return a.every(c,b);j(a,function(a,f,h){if(!(e=e&&c.call(b,a,f,h)))return o});
+return e};var D=b.some=b.any=function(a,c,d){var c=c||b.identity,e=false;if(a==null)return e;if(B&&a.some===B)return a.some(c,d);j(a,function(a,b,h){if(e|=c.call(d,a,b,h))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return q&&a.indexOf===q?a.indexOf(c)!=-1:b=D(a,function(a){if(a===c)return true})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(c.call?c||a:a[c]).apply(a,d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};
+b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&(e={value:a,computed:b})});return e.value};b.shuffle=function(a){var b=[],d;
+j(a,function(a,g){g==0?b[0]=a:(d=Math.floor(Math.random()*(g+1)),b[g]=b[d],b[d]=a)});return b};b.sortBy=function(a,c,d){return b.pluck(b.map(a,function(a,b,f){return{value:a,criteria:c.call(d,a,b,f)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,g=a.length;e<
+g;){var f=e+g>>1;d(a[f])<d(c)?e=f+1:g=f}return e};b.toArray=function(a){return!a?[]:a.toArray?a.toArray():b.isArray(a)?i.call(a):b.isArguments(a)?i.call(a):b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=b.head=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,a.length-b):a[a.length-1]};b.rest=b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=
+function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,f,h){if(0==h||(c===true?b.last(d)!=f:!b.include(d,f)))d[d.length]=f,e[e.length]=a[h];return d},[]);return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};
+b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a,c){return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d)return d=b.sortedIndex(a,c),a[d]===c?d:-1;if(q&&a.indexOf===q)return a.indexOf(c);
+for(d=0,e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(C&&a.lastIndexOf===C)return a.lastIndexOf(b);for(var d=a.length;d--;)if(a[d]===b)return d;return-1};b.range=function(a,b,d){arguments.length<=1&&(b=a||0,a=0);for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),g=0,f=Array(e);g<e;)f[g++]=a,a+=d;return f};var E=function(){};b.bind=function(a,c){var d,e;if(a.bind===s&&s)return s.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;
+e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));E.prototype=a.prototype;var b=new E,f=a.apply(b,e.concat(i.call(arguments)));return Object(f)===f?f:b}};b.bindAll=function(a){var c=i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var b=c.apply(this,arguments);return m.call(d,b)?d[b]:d[b]=a.apply(this,arguments)}};b.delay=
+function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,g,f,h;h=b.debounce(function(){f=false},c);return function(){e=this;g=arguments;var b;d||(d=setTimeout(function(){d=null;a.apply(e,g);h()},c));f||a.apply(e,g);h&&h();f=true}};b.debounce=function(a,b){var d;return function(){var e=this,g=arguments;clearTimeout(d);d=setTimeout(function(){d=null;a.apply(e,
+g)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments));return b.apply(this,d)}};b.compose=function(){var a=i.call(arguments);return function(){for(var b=i.call(arguments),d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return function(){if(--a<1)return b.apply(this,arguments)}};b.keys=H||function(a){if(a!==Object(a))throw new TypeError("Invalid object");
+var b=[],d;for(d in a)m.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},
+a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return u(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(m.call(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=l.call(arguments)=="[object Arguments]"?function(a){return l.call(a)=="[object Arguments]"}:function(a){return!(!a||!m.call(a,
+"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===
+void 0};b.noConflict=function(){r._=F;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")};b.mixin=function(a){j(b.functions(a),function(c){I(c,b[c]=a[c])})};var J=0;b.uniqueId=function(a){var b=J++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,
+interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape,function(a,b){return"',_.escape("+b.replace(/\\'/g,"'")+"),'"}).replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,
+"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",d=new Function("obj",d);return c?d(c):d};var n=function(a){this._wrapped=a};b.prototype=n.prototype;var t=function(a,c){return c?b(a).chain():a},I=function(a,c){n.prototype[a]=function(){var a=i.call(arguments);G.call(a,this._wrapped);return t(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];n.prototype[a]=function(){b.apply(this._wrapped,arguments);return t(this._wrapped,
+this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];n.prototype[a]=function(){return t(b.apply(this._wrapped,arguments),this._chain)}});n.prototype.chain=function(){this._chain=true;return this};n.prototype.value=function(){return this._wrapped}})();
View
958 node_modules/multimethod/node_modules/underscore/underscore.js
@@ -0,0 +1,958 @@
+// Underscore.js 1.2.1
+// (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the MIT license.
+// Portions of Underscore are inspired or borrowed from Prototype,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
+
+(function() {
+
+ // Baseline setup
+ // --------------
+
+ // Establish the root object, `window` in the browser, or `global` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Establish the object that gets returned to break out of a loop iteration.
+ var breaker = {};
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var slice = ArrayProto.slice,
+ unshift = ArrayProto.unshift,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeForEach = ArrayProto.forEach,
+ nativeMap = ArrayProto.map,
+ nativeReduce = ArrayProto.reduce,
+ nativeReduceRight = ArrayProto.reduceRight,
+ nativeFilter = ArrayProto.filter,
+ nativeEvery = ArrayProto.every,
+ nativeSome = ArrayProto.some,
+ nativeIndexOf = ArrayProto.indexOf,
+ nativeLastIndexOf = ArrayProto.lastIndexOf,
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind;
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) { return new wrapper(obj); };
+
+ // Export the Underscore object for **Node.js** and **"CommonJS"**, with
+ // backwards-compatibility for the old `require()` API. If we're not in
+ // CommonJS, add `_` to the global object.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else if (typeof define === 'function' && define.amd) {
+ // Register as a named module with AMD.
+ define('underscore', function() {
+ return _;
+ });
+ } else {
+ // Exported as a string, for Closure Compiler "advanced" mode.
+ root['_'] = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.2.1';
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles objects with the built-in `forEach`, arrays, and raw objects.
+ // Delegates to **ECMAScript 5**'s native `forEach` if available.
+ var each = _.each = _.forEach = function(obj, iterator, context) {
+ if (obj == null) return;
+ if (nativeForEach && obj.forEach === nativeForEach) {
+ obj.forEach(iterator, context);
+ } else if (obj.length === +obj.length) {
+ for (var i = 0, l = obj.length; i < l; i++) {
+ if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
+ }
+ } else {
+ for (var key in obj) {
+ if (hasOwnProperty.call(obj, key)) {
+ if (iterator.call(context, obj[key], key, obj) === breaker) return;
+ }
+ }
+ }
+ };
+
+ // Return the results of applying the iterator to each element.
+ // Delegates to **ECMAScript 5**'s native `map` if available.
+ _.map = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+ each(obj, function(value, index, list) {
+ results[results.length] = iterator.call(context, value, index, list);
+ });
+ return results;
+ };
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
+ _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
+ var initial = memo !== void 0;
+ if (obj == null) obj = [];
+ if (nativeReduce && obj.reduce === nativeReduce) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+ }
+ each(obj, function(value, index, list) {
+ if (!initial) {
+ memo = value;
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, value, index, list);
+ }
+ });
+ if (!initial) throw new TypeError("Reduce of empty array with no initial value");
+ return memo;
+ };
+
+ // The right-associative version of reduce, also known as `foldr`.
+ // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
+ _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+ if (obj == null) obj = [];
+ if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+ if (context) iterator = _.bind(iterator, context);
+ return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+ }
+ var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
+ return _.reduce(reversed, iterator, memo, context);
+ };
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, iterator, context) {
+ var result;
+ any(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ return true;
+ }
+ });
+ return result;
+ };
+
+ // Return all the elements that pass a truth test.
+ // Delegates to **ECMAScript 5**'s native `filter` if available.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+ each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ each(obj, function(value, index, list) {
+ if (!iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Delegates to **ECMAScript 5**'s native `every` if available.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, iterator, context) {
+ var result = true;
+ if (obj == null) return result;
+ if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+ each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+ });
+ return result;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Delegates to **ECMAScript 5**'s native `some` if available.
+ // Aliased as `any`.
+ var any = _.some = _.any = function(obj, iterator, context) {
+ iterator = iterator || _.identity;
+ var result = false;
+ if (obj == null) return result;
+ if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+ each(obj, function(value, index, list) {
+ if (result |= iterator.call(context, value, index, list)) return breaker;
+ });
+ return !!result;
+ };
+
+ // Determine if a given value is included in the array or object using `===`.
+ // Aliased as `contains`.
+ _.include = _.contains = function(obj, target) {
+ var found = false;
+ if (obj == null) return found;
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+ found = any(obj, function(value) {
+ if (value === target) return true;
+ });
+ return found;
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ return _.map(obj, function(value) {
+ return (method.call ? method || value : value[method]).apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+
+ // Return the maximum element or (element-based computation).
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
+ if (!iterator && _.isEmpty(obj)) return -Infinity;
+ var result = {computed : -Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
+ if (!iterator && _.isEmpty(obj)) return Infinity;
+ var result = {computed : Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Shuffle an array.
+ _.shuffle = function(obj) {
+ var shuffled = [], rand;
+ each(obj, function(value, index, list) {
+ if (index == 0) {
+ shuffled[0] = value;
+ } else {
+ rand = Math.floor(Math.random() * (index + 1));
+ shuffled[index] = shuffled[rand];
+ shuffled[rand] = value;
+ }
+ });
+ return shuffled;
+ };
+
+ // Sort the object's values by a criterion produced by an iterator.
+ _.sortBy = function(obj, iterator, context) {
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }), 'value');
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = function(obj, val) {
+ var result = {};
+ var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
+ each(obj, function(value, index) {
+ var key = iterator(value, index);
+ (result[key] || (result[key] = [])).push(value);
+ });
+ return result;
+ };
+
+ // Use a comparator function to figure out at what index an object should
+ // be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator) {
+ iterator || (iterator = _.identity);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >> 1;
+ iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+
+ // Safely convert anything iterable into a real, live array.
+ _.toArray = function(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ if (_.isArray(iterable)) return slice.call(iterable);
+ if (_.isArguments(iterable)) return slice.call(iterable);
+ return _.values(iterable);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ return _.toArray(obj).length;
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head`. The **guard** check allows it to work
+ // with `_.map`.
+ _.first = _.head = function(array, n, guard) {
+ return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+ };
+
+ // Returns everything but the last entry of the array. Especcialy useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N. The **guard** check allows it to work with
+ // `_.map`.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array. The **guard** check allows it to work with `_.map`.
+ _.last = function(array, n, guard) {
+ return (n != null) && !guard ? slice.call(array, array.length - n) : array[array.length - 1];
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail`.
+ // Especially useful on the arguments object. Passing an **index** will return
+ // the rest of the values in the array from that index onward. The **guard**
+ // check allows it to work with `_.map`.
+ _.rest = _.tail = function(array, index, guard) {
+ return slice.call(array, (index == null) || guard ? 1 : index);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, function(value){ return !!value; });
+ };
+
+ // Return a completely flattened version of an array.
+ _.flatten = function(array, shallow) {
+ return _.reduce(array, function(memo, value) {
+ if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
+ memo[memo.length] = value;
+ return memo;
+ }, []);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iterator) {
+ var initial = iterator ? _.map(array, iterator) : array;
+ var result = [];
+ _.reduce(initial, function(memo, el, i) {
+ if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
+ memo[memo.length] = el;
+ result[result.length] = array[i];
+ }
+ return memo;
+ }, []);
+ return result;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(_.flatten(arguments, true));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays. (Aliased as "intersect" for back-compat.)
+ _.intersection = _.intersect = function(array) {
+ var rest = slice.call(arguments, 1);
+ return _.filter(_.uniq(array), function(item) {
+ return _.every(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+
+ // Take the difference between one array and another.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array, other) {
+ return _.filter(array, function(value){ return !_.include(other, value); });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ var args = slice.call(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
+ return results;
+ };
+
+ // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
+ // we need this function. Return the position of the first occurrence of an
+ // item in an array, or -1 if the item is not included in the array.
+ // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = function(array, item, isSorted) {
+ if (array == null) return -1;
+ var i, l;
+ if (isSorted) {
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
+ }
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return