├── CNAME ├── .gitignore ├── favicon.ico ├── docs ├── favicon.ico ├── images │ ├── background.png │ └── underscore.png ├── public │ ├── fonts │ │ ├── aller-bold.eot │ │ ├── aller-bold.ttf │ │ ├── aller-bold.woff │ │ ├── aller-light.eot │ │ ├── aller-light.ttf │ │ ├── aller-light.woff │ │ ├── roboto-black.eot │ │ ├── roboto-black.ttf │ │ └── roboto-black.woff │ └── stylesheets │ │ └── normalize.css └── docco.css ├── bower.json ├── component.json ├── test ├── .eslintrc ├── index.html ├── chaining.js ├── cross-document.js ├── vendor │ ├── qunit.css │ └── qunit-extras.js ├── utility.js ├── functions.js ├── arrays.js └── collections.js ├── CONTRIBUTING.md ├── .eslintrc ├── karma.conf.js ├── LICENSE ├── README.md ├── package.json ├── .travis.yml ├── karma.conf-sauce.js ├── underscore-min.js └── underscore-min.map /CNAME: -------------------------------------------------------------------------------- 1 | underscorejs.org 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | raw 2 | node_modules 3 | *.log 4 | *.idea 5 | *.swp 6 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/favicon.ico -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/favicon.ico -------------------------------------------------------------------------------- /docs/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/images/background.png -------------------------------------------------------------------------------- /docs/images/underscore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/images/underscore.png -------------------------------------------------------------------------------- /docs/public/fonts/aller-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/public/fonts/aller-bold.eot -------------------------------------------------------------------------------- /docs/public/fonts/aller-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/public/fonts/aller-bold.ttf -------------------------------------------------------------------------------- /docs/public/fonts/aller-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/public/fonts/aller-bold.woff -------------------------------------------------------------------------------- /docs/public/fonts/aller-light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/public/fonts/aller-light.eot -------------------------------------------------------------------------------- /docs/public/fonts/aller-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/public/fonts/aller-light.ttf -------------------------------------------------------------------------------- /docs/public/fonts/aller-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/public/fonts/aller-light.woff -------------------------------------------------------------------------------- /docs/public/fonts/roboto-black.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/public/fonts/roboto-black.eot -------------------------------------------------------------------------------- /docs/public/fonts/roboto-black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/public/fonts/roboto-black.ttf -------------------------------------------------------------------------------- /docs/public/fonts/roboto-black.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/underscore/a11976edb79bf15e034e71a7bbf03281728e685e/docs/public/fonts/roboto-black.woff -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "underscore", 3 | "version": "1.8.3", 4 | "main": "underscore.js", 5 | "keywords": ["util", "functional", "server", "client", "browser"], 6 | "ignore" : ["docs", "test", "*.yml", "CNAME", "index.html", "favicon.ico", "CONTRIBUTING.md", ".*", "component.json", "package.json", "karma.*"] 7 | } 8 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "underscore", 3 | "description" : "JavaScript's functional programming helper library.", 4 | "keywords" : ["util", "functional", "server", "client", "browser"], 5 | "repo" : "jashkenas/underscore", 6 | "main" : "underscore.js", 7 | "scripts" : ["underscore.js"], 8 | "version" : "1.8.3", 9 | "license" : "MIT" 10 | } 11 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true 4 | }, 5 | "globals": { 6 | "_": false, 7 | "test": false, 8 | "ok": false, 9 | "is": false, 10 | "equal": false, 11 | "deepEqual": false, 12 | "strictEqual": false, 13 | "notStrictEqual": false, 14 | "notEqual": false, 15 | "throws": false, 16 | "asyncTest": false, 17 | "start": false, 18 | "expect": false, 19 | "QUnit": false 20 | }, 21 | "rules": { 22 | "brace-style": 0, 23 | "dot-notation": 1, 24 | "no-new-wrappers": 0, 25 | "no-sparse-arrays": 0, 26 | "no-extend-native": 0 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Underscore Test Suite 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## How to contribute to Underscore.js 2 | 3 | * Before you open a ticket or send a pull request, [search](https://github.com/jashkenas/underscore/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one. 4 | 5 | * If you're proposing a new feature, make sure it isn't already implemented in [Underscore-Contrib](https://github.com/documentcloud/underscore-contrib). 6 | 7 | * Before sending a pull request for a feature, be sure to have [tests](http://underscorejs.org/test/). 8 | 9 | * Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/underscore/blob/master/underscore.js). 10 | 11 | * In your pull request, do not add documentation or re-build the minified `underscore-min.js` file. We'll do those things before cutting a new release. 12 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "amd": true 6 | }, 7 | 8 | "rules": { 9 | "brace-style": [1, "1tbs"], 10 | "curly": [0, "multi"], 11 | "eqeqeq": [1, "smart"], 12 | "max-depth": [1, 4], 13 | "max-params": [1, 5], 14 | "new-cap": 2, 15 | "new-parens": 0, 16 | "no-constant-condition": 0, 17 | "no-div-regex": 1, 18 | "no-else-return": 1, 19 | "no-extra-parens": 1, 20 | "no-floating-decimal": 2, 21 | "no-inner-declarations": 2, 22 | "no-lonely-if": 1, 23 | "no-nested-ternary": 2, 24 | "no-new-object": 0, 25 | "no-new-func": 0, 26 | "no-underscore-dangle": 0, 27 | "quotes": [2, "single", "avoid-escape"], 28 | "radix": 2, 29 | "space-after-keywords": [2, "always"], 30 | "space-in-brackets": [2, "never"], 31 | "space-unary-word-ops": 2, 32 | "strict": 0, 33 | "wrap-iife": 2 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Note some browser launchers should be installed before using karma start. 2 | 3 | // For example: 4 | // $ npm install karma-firefox-launcher 5 | // $ karma start --browser=Firefox 6 | 7 | // See http://karma-runner.github.io/0.8/config/configuration-file.html 8 | module.exports = function(config) { 9 | config.set({ 10 | basePath: '', 11 | frameworks: ['qunit'], 12 | logLevel: config.LOG_INFO, 13 | port: 9876, 14 | 15 | // list of files / patterns to load in the browser 16 | files: [ 17 | 'test/vendor/qunit-extras.js', 18 | 'underscore.js', 19 | 'test/*.js' 20 | ], 21 | 22 | // Test results reporter to use 23 | // https://npmjs.org/browse/keyword/karma-reporter 24 | reporters: ['progress'], 25 | 26 | // start these browsers 27 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 28 | browsers: ['PhantomJS'], 29 | 30 | // Continuous Integration mode 31 | // if true, Karma captures browsers, runs the tests and exits 32 | singleRun: true 33 | }); 34 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative 2 | Reporters & Editors 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | __ 2 | /\ \ __ 3 | __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____ 4 | /\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\ 5 | \ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\ 6 | \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/ 7 | \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/ 8 | \ \____/ 9 | \/___/ 10 | 11 | Underscore.js is a utility-belt library for JavaScript that provides 12 | support for the usual functional suspects (each, map, reduce, filter...) 13 | without extending any core JavaScript objects. 14 | 15 | For Docs, License, Tests, and pre-packed downloads, see: 16 | http://underscorejs.org 17 | 18 | Underscore is an open-sourced component of DocumentCloud: 19 | https://github.com/documentcloud 20 | 21 | Many thanks to our contributors: 22 | https://github.com/jashkenas/underscore/contributors 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "underscore", 3 | "description": "JavaScript's functional programming helper library.", 4 | "homepage": "http://underscorejs.org", 5 | "keywords": [ 6 | "util", 7 | "functional", 8 | "server", 9 | "client", 10 | "browser" 11 | ], 12 | "author": "Jeremy Ashkenas ", 13 | "repository": { 14 | "type": "git", 15 | "url": "git://github.com/jashkenas/underscore.git" 16 | }, 17 | "main": "underscore.js", 18 | "version": "1.8.3", 19 | "devDependencies": { 20 | "docco": "*", 21 | "eslint": "0.6.x", 22 | "karma": "~0.12.31", 23 | "karma-qunit": "~0.1.4", 24 | "qunit-cli": "~0.2.0", 25 | "uglify-js": "2.4.x" 26 | }, 27 | "scripts": { 28 | "test": "npm run test-node && npm run lint", 29 | "lint": "eslint underscore.js test/*.js", 30 | "test-node": "qunit-cli test/*.js", 31 | "test-browser": "npm i karma-phantomjs-launcher && ./node_modules/karma/bin/karma start", 32 | "build": "uglifyjs underscore.js -c \"evaluate=false\" --comments \"/ .*/\" -m --source-map underscore-min.map -o underscore-min.js", 33 | "doc": "docco underscore.js" 34 | }, 35 | "license": "MIT", 36 | "files": [ 37 | "underscore.js", 38 | "underscore-min.js", 39 | "underscore-min.map", 40 | "LICENSE" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.8" 4 | - "0.12" 5 | - "io.js" 6 | matrix: 7 | include: 8 | - node_js: "0.10" 9 | env: BROWSER=true 10 | before_install: 11 | - npm install -g npm@2.6 12 | - npm install -g karma-cli 13 | before_script: 14 | - npm install karma-sauce-launcher 15 | - export DISPLAY=:99.0 16 | - sh -e /etc/init.d/xvfb start 17 | script: 18 | - npm test 19 | - "[ $BROWSER == false ] || npm run test-browser" 20 | # Karma sauce is limited to running about 5-7 browsers (or it will tiemout) at a time so we just run vendor by vendor here 21 | - "[ $BROWSER == false ] || karma start karma.conf-sauce.js --browsers FIREFOX_V4,FIREFOX_V11,FIREFOX_V20,FIREFOX_V30,FIREFOX_V35" 22 | - "[ $BROWSER == false ] || karma start karma.conf-sauce.js --browsers CHROME_V28,CHROME_V35,CHROME_V40,ANDROID_V4.0,ANDROID_V4.3" 23 | - "[ $BROWSER == false ] || karma start karma.conf-sauce.js --browsers INTERNET_EXPLORER_V9,INTERNET_EXPLORER_V10,INTERNET_EXPLORER_V11" 24 | - "[ $BROWSER == false ] || karma start karma.conf-sauce.js --browsers SAFARI_V5,SAFARI_V6,SAFARI_V7" 25 | - "[ $BROWSER == false ] || karma start karma.conf-sauce.js --browsers OPERA_V11,OPERA_V12" 26 | notifications: 27 | email: false 28 | env: 29 | global: 30 | - secure: bDZSBQfqr21hCayjcZ20IxrV6+XGhxQPFIfwWqEKLrF93Gu8LLVjZRxXE/mE8I8N4Z5WtDNb4ZHrm/TTzmcPa5MuHgIxEdknQCncobH8oimwc83SHwEPk6okeNKl39VlCjvvnmoe/V/KpnknuYn3Rqghtl/Uv9KLpCwskwjTtcw= 31 | - secure: SRECgXuwcZTcD3GVxTS2bYNgRyye4vq6BLrV2PH9FyNenowsKQR2EwlC/dppc1Q8NWMgv79J/R96q9JOFh+mEH9L5dlBb2yhnGH8amVeM/ChAJHT/F8YktKM453uVpz5fR00QcCQDDUOx6Pvx374ID0OKNpWKAkQBWA9mPTsLnE= 32 | matrix: BROWSER=false -------------------------------------------------------------------------------- /karma.conf-sauce.js: -------------------------------------------------------------------------------- 1 | var _ = require('./'); 2 | 3 | // Browsers to run on Sauce Labs platforms 4 | var sauceBrowsers = _.reduce([ 5 | ['firefox', '35'], 6 | ['firefox', '30'], 7 | ['firefox', '20'], 8 | ['firefox', '11'], 9 | ['firefox', '4'], 10 | 11 | ['chrome', '40'], 12 | ['chrome', '35'], 13 | ['chrome', '28'], 14 | 15 | ['internet explorer', '11', 'Windows 8.1'], 16 | ['internet explorer', '10', 'Windows 8'], 17 | ['internet explorer', '9', 'Windows 7'], 18 | // Currently do not work with Karma. 19 | // ['internet explorer', '8', 'Windows 7'], 20 | // ['internet explorer', '7', 'Windows XP'], 21 | // ['internet explorer', '6', 'Windows XP'], 22 | 23 | ['opera', '12'], 24 | ['opera', '11'], 25 | 26 | ['android', '4.3'], 27 | ['android', '4.0'], 28 | 29 | ['safari', '8'], 30 | ['safari', '6'], 31 | ['safari', '7'], 32 | ['safari', '5'] 33 | ], function(memo, platform) { 34 | var label = (platform[0] + '_v' + platform[1]).replace(' ', '_').toUpperCase(); 35 | memo[label] = _.pick({ 36 | 'base': 'SauceLabs', 37 | 'browserName': platform[0], 38 | 'version': platform[1], 39 | 'platform': platform[2] 40 | }, Boolean); 41 | return memo; 42 | }, {}); 43 | 44 | module.exports = function(config) { 45 | if ( !process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY ) { 46 | console.log('Sauce environments not set --- Skipping'); 47 | return process.exit(0); 48 | } 49 | 50 | config.set({ 51 | basePath: '', 52 | frameworks: ['qunit'], 53 | singleRun: true, 54 | 55 | // list of files / patterns to load in the browser 56 | files: [ 57 | 'test/vendor/qunit-extras.js', 58 | 'underscore.js', 59 | 'test/*.js' 60 | ], 61 | // test results reporter to use 62 | reporters: ['dots', 'saucelabs'], 63 | port: 9876, 64 | colors: true, 65 | logLevel: config.LOG_INFO, 66 | sauceLabs: { 67 | build: 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')', 68 | startConnect: true, 69 | tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER 70 | }, 71 | 72 | // TODO(vojta): remove once SauceLabs supports websockets. 73 | // This speeds up the capturing a bit, as browsers don't even try to use websocket. 74 | transports: ['xhr-polling'], 75 | captureTimeout: 120000, 76 | customLaunchers: sauceBrowsers 77 | 78 | // Browsers to launch, commented out to prevent karma from starting 79 | // too many concurrent browsers and timing sauce out. 80 | // browsers: _.keys(sauceBrowsers) 81 | }); 82 | }; 83 | -------------------------------------------------------------------------------- /test/chaining.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var _ = typeof require == 'function' ? require('..') : window._; 3 | 4 | QUnit.module('Chaining'); 5 | 6 | test('map/flatten/reduce', function() { 7 | var lyrics = [ 8 | 'I\'m a lumberjack and I\'m okay', 9 | 'I sleep all night and I work all day', 10 | 'He\'s a lumberjack and he\'s okay', 11 | 'He sleeps all night and he works all day' 12 | ]; 13 | var counts = _(lyrics).chain() 14 | .map(function(line) { return line.split(''); }) 15 | .flatten() 16 | .reduce(function(hash, l) { 17 | hash[l] = hash[l] || 0; 18 | hash[l]++; 19 | return hash; 20 | }, {}).value(); 21 | equal(counts.a, 16, 'counted all the letters in the song'); 22 | equal(counts.e, 10, 'counted all the letters in the song'); 23 | }); 24 | 25 | test('select/reject/sortBy', function() { 26 | var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 27 | numbers = _(numbers).chain().select(function(n) { 28 | return n % 2 === 0; 29 | }).reject(function(n) { 30 | return n % 4 === 0; 31 | }).sortBy(function(n) { 32 | return -n; 33 | }).value(); 34 | deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers'); 35 | }); 36 | 37 | test('select/reject/sortBy in functional style', function() { 38 | var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 39 | numbers = _.chain(numbers).select(function(n) { 40 | return n % 2 === 0; 41 | }).reject(function(n) { 42 | return n % 4 === 0; 43 | }).sortBy(function(n) { 44 | return -n; 45 | }).value(); 46 | deepEqual(numbers, [10, 6, 2], 'filtered and reversed the numbers'); 47 | }); 48 | 49 | test('reverse/concat/unshift/pop/map', function() { 50 | var numbers = [1, 2, 3, 4, 5]; 51 | numbers = _(numbers).chain() 52 | .reverse() 53 | .concat([5, 5, 5]) 54 | .unshift(17) 55 | .pop() 56 | .map(function(n){ return n * 2; }) 57 | .value(); 58 | deepEqual(numbers, [34, 10, 8, 6, 4, 2, 10, 10], 'can chain together array functions.'); 59 | }); 60 | 61 | test('splice', function() { 62 | var instance = _([1, 2, 3, 4, 5]).chain(); 63 | deepEqual(instance.splice(1, 3).value(), [1, 5]); 64 | deepEqual(instance.splice(1, 0).value(), [1, 5]); 65 | deepEqual(instance.splice(1, 1).value(), [1]); 66 | deepEqual(instance.splice(0, 1).value(), [], '#397 Can create empty array'); 67 | }); 68 | 69 | test('shift', function() { 70 | var instance = _([1, 2, 3]).chain(); 71 | deepEqual(instance.shift().value(), [2, 3]); 72 | deepEqual(instance.shift().value(), [3]); 73 | deepEqual(instance.shift().value(), [], '#397 Can create empty array'); 74 | }); 75 | 76 | test('pop', function() { 77 | var instance = _([1, 2, 3]).chain(); 78 | deepEqual(instance.pop().value(), [1, 2]); 79 | deepEqual(instance.pop().value(), [1]); 80 | deepEqual(instance.pop().value(), [], '#397 Can create empty array'); 81 | }); 82 | 83 | test('chaining works in small stages', function() { 84 | var o = _([1, 2, 3, 4]).chain(); 85 | deepEqual(o.filter(function(i) { return i < 3; }).value(), [1, 2]); 86 | deepEqual(o.filter(function(i) { return i > 2; }).value(), [3, 4]); 87 | }); 88 | 89 | test('#1562: Engine proxies for chained functions', function() { 90 | var wrapped = _(512); 91 | strictEqual(wrapped.toJSON(), 512); 92 | strictEqual(wrapped.valueOf(), 512); 93 | strictEqual(+wrapped, 512); 94 | strictEqual(wrapped.toString(), '512'); 95 | strictEqual('' + wrapped, '512'); 96 | }); 97 | 98 | }()); 99 | -------------------------------------------------------------------------------- /test/cross-document.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | if (typeof document == 'undefined') return; 3 | 4 | var _ = typeof require == 'function' ? require('..') : window._; 5 | 6 | QUnit.module('Cross Document'); 7 | /* global iObject, iElement, iArguments, iFunction, iArray, iError, iString, iNumber, iBoolean, iDate, iRegExp, iNaN, iNull, iUndefined, ActiveXObject */ 8 | 9 | // Setup remote variables for iFrame tests. 10 | var iframe = document.createElement('iframe'); 11 | iframe.frameBorder = iframe.height = iframe.width = 0; 12 | document.body.appendChild(iframe); 13 | var iDoc = (iDoc = iframe.contentDocument || iframe.contentWindow).document || iDoc; 14 | iDoc.write( 15 | [ 16 | '' 32 | ].join('\n') 33 | ); 34 | iDoc.close(); 35 | 36 | test('isEqual', function() { 37 | 38 | ok(!_.isEqual(iNumber, 101)); 39 | ok(_.isEqual(iNumber, 100)); 40 | 41 | // Objects from another frame. 42 | ok(_.isEqual({}, iObject), 'Objects with equivalent members created in different documents are equal'); 43 | 44 | // Array from another frame. 45 | ok(_.isEqual([1, 2, 3], iArray), 'Arrays with equivalent elements created in different documents are equal'); 46 | }); 47 | 48 | test('isEmpty', function() { 49 | ok(!_([iNumber]).isEmpty(), '[1] is not empty'); 50 | ok(!_.isEmpty(iArray), '[] is empty'); 51 | ok(_.isEmpty(iObject), '{} is empty'); 52 | }); 53 | 54 | test('isElement', function() { 55 | ok(!_.isElement('div'), 'strings are not dom elements'); 56 | ok(_.isElement(document.body), 'the body tag is a DOM element'); 57 | ok(_.isElement(iElement), 'even from another frame'); 58 | }); 59 | 60 | test('isArguments', function() { 61 | ok(_.isArguments(iArguments), 'even from another frame'); 62 | }); 63 | 64 | test('isObject', function() { 65 | ok(_.isObject(iElement), 'even from another frame'); 66 | ok(_.isObject(iFunction), 'even from another frame'); 67 | }); 68 | 69 | test('isArray', function() { 70 | ok(_.isArray(iArray), 'even from another frame'); 71 | }); 72 | 73 | test('isString', function() { 74 | ok(_.isString(iString), 'even from another frame'); 75 | }); 76 | 77 | test('isNumber', function() { 78 | ok(_.isNumber(iNumber), 'even from another frame'); 79 | }); 80 | 81 | test('isBoolean', function() { 82 | ok(_.isBoolean(iBoolean), 'even from another frame'); 83 | }); 84 | 85 | test('isFunction', function() { 86 | ok(_.isFunction(iFunction), 'even from another frame'); 87 | }); 88 | 89 | test('isDate', function() { 90 | ok(_.isDate(iDate), 'even from another frame'); 91 | }); 92 | 93 | test('isRegExp', function() { 94 | ok(_.isRegExp(iRegExp), 'even from another frame'); 95 | }); 96 | 97 | test('isNaN', function() { 98 | ok(_.isNaN(iNaN), 'even from another frame'); 99 | }); 100 | 101 | test('isNull', function() { 102 | ok(_.isNull(iNull), 'even from another frame'); 103 | }); 104 | 105 | test('isUndefined', function() { 106 | ok(_.isUndefined(iUndefined), 'even from another frame'); 107 | }); 108 | 109 | test('isError', function() { 110 | ok(_.isError(iError), 'even from another frame'); 111 | }); 112 | 113 | if (typeof ActiveXObject != 'undefined') { 114 | test('IE host objects', function() { 115 | var xml = new ActiveXObject('Msxml2.DOMDocument.3.0'); 116 | ok(!_.isNumber(xml)); 117 | ok(!_.isBoolean(xml)); 118 | ok(!_.isNaN(xml)); 119 | ok(!_.isFunction(xml)); 120 | ok(!_.isNull(xml)); 121 | ok(!_.isUndefined(xml)); 122 | }); 123 | 124 | test('#1621 IE 11 compat mode DOM elements are not functions', function() { 125 | var fn = function() {}; 126 | var xml = new ActiveXObject('Msxml2.DOMDocument.3.0'); 127 | var div = document.createElement('div'); 128 | 129 | // JIT the function 130 | var count = 200; 131 | while (count--) { 132 | _.isFunction(fn); 133 | } 134 | 135 | equal(_.isFunction(xml), false); 136 | equal(_.isFunction(div), false); 137 | equal(_.isFunction(fn), true); 138 | }); 139 | } 140 | 141 | }()); -------------------------------------------------------------------------------- /test/vendor/qunit.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * QUnit 1.17.1 3 | * http://qunitjs.com/ 4 | * 5 | * Copyright jQuery Foundation and other contributors 6 | * Released under the MIT license 7 | * http://jquery.org/license 8 | * 9 | * Date: 2015-01-20T19:39Z 10 | */ 11 | 12 | /** Font Family and Sizes */ 13 | 14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 16 | } 17 | 18 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 19 | #qunit-tests { font-size: smaller; } 20 | 21 | 22 | /** Resets */ 23 | 24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 25 | margin: 0; 26 | padding: 0; 27 | } 28 | 29 | 30 | /** Header */ 31 | 32 | #qunit-header { 33 | padding: 0.5em 0 0.5em 1em; 34 | 35 | color: #8699A4; 36 | background-color: #0D3349; 37 | 38 | font-size: 1.5em; 39 | line-height: 1em; 40 | font-weight: 400; 41 | 42 | border-radius: 5px 5px 0 0; 43 | } 44 | 45 | #qunit-header a { 46 | text-decoration: none; 47 | color: #C2CCD1; 48 | } 49 | 50 | #qunit-header a:hover, 51 | #qunit-header a:focus { 52 | color: #FFF; 53 | } 54 | 55 | #qunit-testrunner-toolbar label { 56 | display: inline-block; 57 | padding: 0 0.5em 0 0.1em; 58 | } 59 | 60 | #qunit-banner { 61 | height: 5px; 62 | } 63 | 64 | #qunit-testrunner-toolbar { 65 | padding: 0.5em 1em 0.5em 1em; 66 | color: #5E740B; 67 | background-color: #EEE; 68 | overflow: hidden; 69 | } 70 | 71 | #qunit-userAgent { 72 | padding: 0.5em 1em 0.5em 1em; 73 | background-color: #2B81AF; 74 | color: #FFF; 75 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 76 | } 77 | 78 | #qunit-modulefilter-container { 79 | float: right; 80 | padding: 0.2em; 81 | } 82 | 83 | .qunit-url-config { 84 | display: inline-block; 85 | padding: 0.1em; 86 | } 87 | 88 | .qunit-filter { 89 | display: block; 90 | float: right; 91 | margin-left: 1em; 92 | } 93 | 94 | /** Tests: Pass/Fail */ 95 | 96 | #qunit-tests { 97 | list-style-position: inside; 98 | } 99 | 100 | #qunit-tests li { 101 | padding: 0.4em 1em 0.4em 1em; 102 | border-bottom: 1px solid #FFF; 103 | list-style-position: inside; 104 | } 105 | 106 | #qunit-tests > li { 107 | display: none; 108 | } 109 | 110 | #qunit-tests li.running, 111 | #qunit-tests li.pass, 112 | #qunit-tests li.fail, 113 | #qunit-tests li.skipped { 114 | display: list-item; 115 | } 116 | 117 | #qunit-tests.hidepass li.running, 118 | #qunit-tests.hidepass li.pass { 119 | display: none; 120 | } 121 | 122 | #qunit-tests li strong { 123 | cursor: pointer; 124 | } 125 | 126 | #qunit-tests li.skipped strong { 127 | cursor: default; 128 | } 129 | 130 | #qunit-tests li a { 131 | padding: 0.5em; 132 | color: #C2CCD1; 133 | text-decoration: none; 134 | } 135 | #qunit-tests li a:hover, 136 | #qunit-tests li a:focus { 137 | color: #000; 138 | } 139 | 140 | #qunit-tests li .runtime { 141 | float: right; 142 | font-size: smaller; 143 | } 144 | 145 | .qunit-assert-list { 146 | margin-top: 0.5em; 147 | padding: 0.5em; 148 | 149 | background-color: #FFF; 150 | 151 | border-radius: 5px; 152 | } 153 | 154 | .qunit-collapsed { 155 | display: none; 156 | } 157 | 158 | #qunit-tests table { 159 | border-collapse: collapse; 160 | margin-top: 0.2em; 161 | } 162 | 163 | #qunit-tests th { 164 | text-align: right; 165 | vertical-align: top; 166 | padding: 0 0.5em 0 0; 167 | } 168 | 169 | #qunit-tests td { 170 | vertical-align: top; 171 | } 172 | 173 | #qunit-tests pre { 174 | margin: 0; 175 | white-space: pre-wrap; 176 | word-wrap: break-word; 177 | } 178 | 179 | #qunit-tests del { 180 | background-color: #E0F2BE; 181 | color: #374E0C; 182 | text-decoration: none; 183 | } 184 | 185 | #qunit-tests ins { 186 | background-color: #FFCACA; 187 | color: #500; 188 | text-decoration: none; 189 | } 190 | 191 | /*** Test Counts */ 192 | 193 | #qunit-tests b.counts { color: #000; } 194 | #qunit-tests b.passed { color: #5E740B; } 195 | #qunit-tests b.failed { color: #710909; } 196 | 197 | #qunit-tests li li { 198 | padding: 5px; 199 | background-color: #FFF; 200 | border-bottom: none; 201 | list-style-position: inside; 202 | } 203 | 204 | /*** Passing Styles */ 205 | 206 | #qunit-tests li li.pass { 207 | color: #3C510C; 208 | background-color: #FFF; 209 | border-left: 10px solid #C6E746; 210 | } 211 | 212 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 213 | #qunit-tests .pass .test-name { color: #366097; } 214 | 215 | #qunit-tests .pass .test-actual, 216 | #qunit-tests .pass .test-expected { color: #999; } 217 | 218 | #qunit-banner.qunit-pass { background-color: #C6E746; } 219 | 220 | /*** Failing Styles */ 221 | 222 | #qunit-tests li li.fail { 223 | color: #710909; 224 | background-color: #FFF; 225 | border-left: 10px solid #EE5757; 226 | white-space: pre; 227 | } 228 | 229 | #qunit-tests > li:last-child { 230 | border-radius: 0 0 5px 5px; 231 | } 232 | 233 | #qunit-tests .fail { color: #000; background-color: #EE5757; } 234 | #qunit-tests .fail .test-name, 235 | #qunit-tests .fail .module-name { color: #000; } 236 | 237 | #qunit-tests .fail .test-actual { color: #EE5757; } 238 | #qunit-tests .fail .test-expected { color: #008000; } 239 | 240 | #qunit-banner.qunit-fail { background-color: #EE5757; } 241 | 242 | /*** Skipped tests */ 243 | 244 | #qunit-tests .skipped { 245 | background-color: #EBECE9; 246 | } 247 | 248 | #qunit-tests .qunit-skipped-label { 249 | background-color: #F4FF77; 250 | display: inline-block; 251 | font-style: normal; 252 | color: #366097; 253 | line-height: 1.8em; 254 | padding: 0 0.5em; 255 | margin: -0.4em 0.4em -0.4em 0; 256 | } 257 | 258 | /** Result */ 259 | 260 | #qunit-testresult { 261 | padding: 0.5em 1em 0.5em 1em; 262 | 263 | color: #2B81AF; 264 | background-color: #D2E0E6; 265 | 266 | border-bottom: 1px solid #FFF; 267 | } 268 | #qunit-testresult .module-name { 269 | font-weight: 700; 270 | } 271 | 272 | /** Fixture */ 273 | 274 | #qunit-fixture { 275 | position: absolute; 276 | top: -10000px; 277 | left: -10000px; 278 | width: 1000px; 279 | height: 1000px; 280 | } -------------------------------------------------------------------------------- /docs/public/stylesheets/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.0.1 | MIT License | git.io/normalize */ 2 | 3 | /* ========================================================================== 4 | HTML5 display definitions 5 | ========================================================================== */ 6 | 7 | /* 8 | * Corrects `block` display not defined in IE 8/9. 9 | */ 10 | 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | hgroup, 19 | nav, 20 | section, 21 | summary { 22 | display: block; 23 | } 24 | 25 | /* 26 | * Corrects `inline-block` display not defined in IE 8/9. 27 | */ 28 | 29 | audio, 30 | canvas, 31 | video { 32 | display: inline-block; 33 | } 34 | 35 | /* 36 | * Prevents modern browsers from displaying `audio` without controls. 37 | * Remove excess height in iOS 5 devices. 38 | */ 39 | 40 | audio:not([controls]) { 41 | display: none; 42 | height: 0; 43 | } 44 | 45 | /* 46 | * Addresses styling for `hidden` attribute not present in IE 8/9. 47 | */ 48 | 49 | [hidden] { 50 | display: none; 51 | } 52 | 53 | /* ========================================================================== 54 | Base 55 | ========================================================================== */ 56 | 57 | /* 58 | * 1. Sets default font family to sans-serif. 59 | * 2. Prevents iOS text size adjust after orientation change, without disabling 60 | * user zoom. 61 | */ 62 | 63 | html { 64 | font-family: sans-serif; /* 1 */ 65 | -webkit-text-size-adjust: 100%; /* 2 */ 66 | -ms-text-size-adjust: 100%; /* 2 */ 67 | } 68 | 69 | /* 70 | * Removes default margin. 71 | */ 72 | 73 | body { 74 | margin: 0; 75 | } 76 | 77 | /* ========================================================================== 78 | Links 79 | ========================================================================== */ 80 | 81 | /* 82 | * Addresses `outline` inconsistency between Chrome and other browsers. 83 | */ 84 | 85 | a:focus { 86 | outline: thin dotted; 87 | } 88 | 89 | /* 90 | * Improves readability when focused and also mouse hovered in all browsers. 91 | */ 92 | 93 | a:active, 94 | a:hover { 95 | outline: 0; 96 | } 97 | 98 | /* ========================================================================== 99 | Typography 100 | ========================================================================== */ 101 | 102 | /* 103 | * Addresses `h1` font sizes within `section` and `article` in Firefox 4+, 104 | * Safari 5, and Chrome. 105 | */ 106 | 107 | h1 { 108 | font-size: 2em; 109 | } 110 | 111 | /* 112 | * Addresses styling not present in IE 8/9, Safari 5, and Chrome. 113 | */ 114 | 115 | abbr[title] { 116 | border-bottom: 1px dotted; 117 | } 118 | 119 | /* 120 | * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome. 121 | */ 122 | 123 | b, 124 | strong { 125 | font-weight: bold; 126 | } 127 | 128 | /* 129 | * Addresses styling not present in Safari 5 and Chrome. 130 | */ 131 | 132 | dfn { 133 | font-style: italic; 134 | } 135 | 136 | /* 137 | * Addresses styling not present in IE 8/9. 138 | */ 139 | 140 | mark { 141 | background: #ff0; 142 | color: #000; 143 | } 144 | 145 | 146 | /* 147 | * Corrects font family set oddly in Safari 5 and Chrome. 148 | */ 149 | 150 | code, 151 | kbd, 152 | pre, 153 | samp { 154 | font-family: monospace, serif; 155 | font-size: 1em; 156 | } 157 | 158 | /* 159 | * Improves readability of pre-formatted text in all browsers. 160 | */ 161 | 162 | pre { 163 | white-space: pre; 164 | white-space: pre-wrap; 165 | word-wrap: break-word; 166 | } 167 | 168 | /* 169 | * Sets consistent quote types. 170 | */ 171 | 172 | q { 173 | quotes: "\201C" "\201D" "\2018" "\2019"; 174 | } 175 | 176 | /* 177 | * Addresses inconsistent and variable font size in all browsers. 178 | */ 179 | 180 | small { 181 | font-size: 80%; 182 | } 183 | 184 | /* 185 | * Prevents `sub` and `sup` affecting `line-height` in all browsers. 186 | */ 187 | 188 | sub, 189 | sup { 190 | font-size: 75%; 191 | line-height: 0; 192 | position: relative; 193 | vertical-align: baseline; 194 | } 195 | 196 | sup { 197 | top: -0.5em; 198 | } 199 | 200 | sub { 201 | bottom: -0.25em; 202 | } 203 | 204 | /* ========================================================================== 205 | Embedded content 206 | ========================================================================== */ 207 | 208 | /* 209 | * Removes border when inside `a` element in IE 8/9. 210 | */ 211 | 212 | img { 213 | border: 0; 214 | } 215 | 216 | /* 217 | * Corrects overflow displayed oddly in IE 9. 218 | */ 219 | 220 | svg:not(:root) { 221 | overflow: hidden; 222 | } 223 | 224 | /* ========================================================================== 225 | Figures 226 | ========================================================================== */ 227 | 228 | /* 229 | * Addresses margin not present in IE 8/9 and Safari 5. 230 | */ 231 | 232 | figure { 233 | margin: 0; 234 | } 235 | 236 | /* ========================================================================== 237 | Forms 238 | ========================================================================== */ 239 | 240 | /* 241 | * Define consistent border, margin, and padding. 242 | */ 243 | 244 | fieldset { 245 | border: 1px solid #c0c0c0; 246 | margin: 0 2px; 247 | padding: 0.35em 0.625em 0.75em; 248 | } 249 | 250 | /* 251 | * 1. Corrects color not being inherited in IE 8/9. 252 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 253 | */ 254 | 255 | legend { 256 | border: 0; /* 1 */ 257 | padding: 0; /* 2 */ 258 | } 259 | 260 | /* 261 | * 1. Corrects font family not being inherited in all browsers. 262 | * 2. Corrects font size not being inherited in all browsers. 263 | * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome 264 | */ 265 | 266 | button, 267 | input, 268 | select, 269 | textarea { 270 | font-family: inherit; /* 1 */ 271 | font-size: 100%; /* 2 */ 272 | margin: 0; /* 3 */ 273 | } 274 | 275 | /* 276 | * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in 277 | * the UA stylesheet. 278 | */ 279 | 280 | button, 281 | input { 282 | line-height: normal; 283 | } 284 | 285 | /* 286 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 287 | * and `video` controls. 288 | * 2. Corrects inability to style clickable `input` types in iOS. 289 | * 3. Improves usability and consistency of cursor style between image-type 290 | * `input` and others. 291 | */ 292 | 293 | button, 294 | html input[type="button"], /* 1 */ 295 | input[type="reset"], 296 | input[type="submit"] { 297 | -webkit-appearance: button; /* 2 */ 298 | cursor: pointer; /* 3 */ 299 | } 300 | 301 | /* 302 | * Re-set default cursor for disabled elements. 303 | */ 304 | 305 | button[disabled], 306 | input[disabled] { 307 | cursor: default; 308 | } 309 | 310 | /* 311 | * 1. Addresses box sizing set to `content-box` in IE 8/9. 312 | * 2. Removes excess padding in IE 8/9. 313 | */ 314 | 315 | input[type="checkbox"], 316 | input[type="radio"] { 317 | box-sizing: border-box; /* 1 */ 318 | padding: 0; /* 2 */ 319 | } 320 | 321 | /* 322 | * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. 323 | * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome 324 | * (include `-moz` to future-proof). 325 | */ 326 | 327 | input[type="search"] { 328 | -webkit-appearance: textfield; /* 1 */ 329 | -moz-box-sizing: content-box; 330 | -webkit-box-sizing: content-box; /* 2 */ 331 | box-sizing: content-box; 332 | } 333 | 334 | /* 335 | * Removes inner padding and search cancel button in Safari 5 and Chrome 336 | * on OS X. 337 | */ 338 | 339 | input[type="search"]::-webkit-search-cancel-button, 340 | input[type="search"]::-webkit-search-decoration { 341 | -webkit-appearance: none; 342 | } 343 | 344 | /* 345 | * Removes inner padding and border in Firefox 4+. 346 | */ 347 | 348 | button::-moz-focus-inner, 349 | input::-moz-focus-inner { 350 | border: 0; 351 | padding: 0; 352 | } 353 | 354 | /* 355 | * 1. Removes default vertical scrollbar in IE 8/9. 356 | * 2. Improves readability and alignment in all browsers. 357 | */ 358 | 359 | textarea { 360 | overflow: auto; /* 1 */ 361 | vertical-align: top; /* 2 */ 362 | } 363 | 364 | /* ========================================================================== 365 | Tables 366 | ========================================================================== */ 367 | 368 | /* 369 | * Remove most spacing between table cells. 370 | */ 371 | 372 | table { 373 | border-collapse: collapse; 374 | border-spacing: 0; 375 | } -------------------------------------------------------------------------------- /docs/docco.css: -------------------------------------------------------------------------------- 1 | /*--------------------- Typography ----------------------------*/ 2 | 3 | @font-face { 4 | font-family: 'aller-light'; 5 | src: url('public/fonts/aller-light.eot'); 6 | src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'), 7 | url('public/fonts/aller-light.woff') format('woff'), 8 | url('public/fonts/aller-light.ttf') format('truetype'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | @font-face { 14 | font-family: 'aller-bold'; 15 | src: url('public/fonts/aller-bold.eot'); 16 | src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'), 17 | url('public/fonts/aller-bold.woff') format('woff'), 18 | url('public/fonts/aller-bold.ttf') format('truetype'); 19 | font-weight: normal; 20 | font-style: normal; 21 | } 22 | 23 | @font-face { 24 | font-family: 'roboto-black'; 25 | src: url('public/fonts/roboto-black.eot'); 26 | src: url('public/fonts/roboto-black.eot?#iefix') format('embedded-opentype'), 27 | url('public/fonts/roboto-black.woff') format('woff'), 28 | url('public/fonts/roboto-black.ttf') format('truetype'); 29 | font-weight: normal; 30 | font-style: normal; 31 | } 32 | 33 | /*--------------------- Layout ----------------------------*/ 34 | html { height: 100%; } 35 | body { 36 | font-family: "aller-light"; 37 | font-size: 14px; 38 | line-height: 18px; 39 | color: #30404f; 40 | margin: 0; padding: 0; 41 | height:100%; 42 | } 43 | #container { min-height: 100%; } 44 | 45 | a { 46 | color: #000; 47 | } 48 | 49 | b, strong { 50 | font-weight: normal; 51 | font-family: "aller-bold"; 52 | } 53 | 54 | p { 55 | margin: 15px 0 0px; 56 | } 57 | .annotation ul, .annotation ol { 58 | margin: 25px 0; 59 | } 60 | .annotation ul li, .annotation ol li { 61 | font-size: 14px; 62 | line-height: 18px; 63 | margin: 10px 0; 64 | } 65 | 66 | h1, h2, h3, h4, h5, h6 { 67 | color: #112233; 68 | line-height: 1em; 69 | font-weight: normal; 70 | font-family: "roboto-black"; 71 | text-transform: uppercase; 72 | margin: 30px 0 15px 0; 73 | } 74 | 75 | h1 { 76 | margin-top: 40px; 77 | } 78 | h2 { 79 | font-size: 1.26em; 80 | } 81 | 82 | hr { 83 | border: 0; 84 | background: 1px #ddd; 85 | height: 1px; 86 | margin: 20px 0; 87 | } 88 | 89 | pre, tt, code { 90 | font-size: 12px; line-height: 16px; 91 | font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; 92 | margin: 0; padding: 0; 93 | } 94 | .annotation pre { 95 | display: block; 96 | margin: 0; 97 | padding: 7px 10px; 98 | background: #fcfcfc; 99 | -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); 100 | -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); 101 | box-shadow: inset 0 0 10px rgba(0,0,0,0.1); 102 | overflow-x: auto; 103 | } 104 | .annotation pre code { 105 | border: 0; 106 | padding: 0; 107 | background: transparent; 108 | } 109 | 110 | 111 | blockquote { 112 | border-left: 5px solid #ccc; 113 | margin: 0; 114 | padding: 1px 0 1px 1em; 115 | } 116 | .sections blockquote p { 117 | font-family: Menlo, Consolas, Monaco, monospace; 118 | font-size: 12px; line-height: 16px; 119 | color: #999; 120 | margin: 10px 0 0; 121 | white-space: pre-wrap; 122 | } 123 | 124 | ul.sections { 125 | list-style: none; 126 | padding:0 0 5px 0;; 127 | margin:0; 128 | } 129 | 130 | /* 131 | Force border-box so that % widths fit the parent 132 | container without overlap because of margin/padding. 133 | 134 | More Info : http://www.quirksmode.org/css/box.html 135 | */ 136 | ul.sections > li > div { 137 | -moz-box-sizing: border-box; /* firefox */ 138 | -ms-box-sizing: border-box; /* ie */ 139 | -webkit-box-sizing: border-box; /* webkit */ 140 | -khtml-box-sizing: border-box; /* konqueror */ 141 | box-sizing: border-box; /* css3 */ 142 | } 143 | 144 | 145 | /*---------------------- Jump Page -----------------------------*/ 146 | #jump_to, #jump_page { 147 | margin: 0; 148 | background: white; 149 | -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; 150 | -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; 151 | font: 16px Arial; 152 | cursor: pointer; 153 | text-align: right; 154 | list-style: none; 155 | } 156 | 157 | #jump_to a { 158 | text-decoration: none; 159 | } 160 | 161 | #jump_to a.large { 162 | display: none; 163 | } 164 | #jump_to a.small { 165 | font-size: 22px; 166 | font-weight: bold; 167 | color: #676767; 168 | } 169 | 170 | #jump_to, #jump_wrapper { 171 | position: fixed; 172 | right: 0; top: 0; 173 | padding: 10px 15px; 174 | margin:0; 175 | } 176 | 177 | #jump_wrapper { 178 | display: none; 179 | padding:0; 180 | } 181 | 182 | #jump_to:hover #jump_wrapper { 183 | display: block; 184 | } 185 | 186 | #jump_page_wrapper{ 187 | position: fixed; 188 | right: 0; 189 | top: 0; 190 | bottom: 0; 191 | } 192 | 193 | #jump_page { 194 | padding: 5px 0 3px; 195 | margin: 0 0 25px 25px; 196 | max-height: 100%; 197 | overflow: auto; 198 | } 199 | 200 | #jump_page .source { 201 | display: block; 202 | padding: 15px; 203 | text-decoration: none; 204 | border-top: 1px solid #eee; 205 | } 206 | 207 | #jump_page .source:hover { 208 | background: #f5f5ff; 209 | } 210 | 211 | #jump_page .source:first-child { 212 | } 213 | 214 | /*---------------------- Low resolutions (> 320px) ---------------------*/ 215 | @media only screen and (min-width: 320px) { 216 | .pilwrap { display: none; } 217 | 218 | ul.sections > li > div { 219 | display: block; 220 | padding:5px 10px 0 10px; 221 | } 222 | 223 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { 224 | padding-left: 30px; 225 | } 226 | 227 | ul.sections > li > div.content { 228 | overflow-x:auto; 229 | -webkit-box-shadow: inset 0 0 5px #e5e5ee; 230 | box-shadow: inset 0 0 5px #e5e5ee; 231 | border: 1px solid #dedede; 232 | margin:5px 10px 5px 10px; 233 | padding-bottom: 5px; 234 | } 235 | 236 | ul.sections > li > div.annotation pre { 237 | margin: 7px 0 7px; 238 | padding-left: 15px; 239 | } 240 | 241 | ul.sections > li > div.annotation p tt, .annotation code { 242 | background: #f8f8ff; 243 | border: 1px solid #dedede; 244 | font-size: 12px; 245 | padding: 0 0.2em; 246 | } 247 | } 248 | 249 | /*---------------------- (> 481px) ---------------------*/ 250 | @media only screen and (min-width: 481px) { 251 | #container { 252 | position: relative; 253 | } 254 | body { 255 | background-color: #F5F5FF; 256 | font-size: 15px; 257 | line-height: 21px; 258 | } 259 | pre, tt, code { 260 | line-height: 18px; 261 | } 262 | p, ul, ol { 263 | margin: 0 0 15px; 264 | } 265 | 266 | 267 | #jump_to { 268 | padding: 5px 10px; 269 | } 270 | #jump_wrapper { 271 | padding: 0; 272 | } 273 | #jump_to, #jump_page { 274 | font: 10px Arial; 275 | text-transform: uppercase; 276 | } 277 | #jump_page .source { 278 | padding: 5px 10px; 279 | } 280 | #jump_to a.large { 281 | display: inline-block; 282 | } 283 | #jump_to a.small { 284 | display: none; 285 | } 286 | 287 | 288 | 289 | #background { 290 | position: absolute; 291 | top: 0; bottom: 0; 292 | width: 350px; 293 | background: #fff; 294 | border-right: 1px solid #e5e5ee; 295 | z-index: -1; 296 | } 297 | 298 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { 299 | padding-left: 40px; 300 | } 301 | 302 | ul.sections > li { 303 | white-space: nowrap; 304 | } 305 | 306 | ul.sections > li > div { 307 | display: inline-block; 308 | } 309 | 310 | ul.sections > li > div.annotation { 311 | max-width: 350px; 312 | min-width: 350px; 313 | min-height: 5px; 314 | padding: 13px; 315 | overflow-x: hidden; 316 | white-space: normal; 317 | vertical-align: top; 318 | text-align: left; 319 | } 320 | ul.sections > li > div.annotation pre { 321 | margin: 15px 0 15px; 322 | padding-left: 15px; 323 | } 324 | 325 | ul.sections > li > div.content { 326 | padding: 13px; 327 | vertical-align: top; 328 | border: none; 329 | -webkit-box-shadow: none; 330 | box-shadow: none; 331 | } 332 | 333 | .pilwrap { 334 | position: relative; 335 | display: inline; 336 | } 337 | 338 | .pilcrow { 339 | font: 12px Arial; 340 | text-decoration: none; 341 | color: #454545; 342 | position: absolute; 343 | top: 3px; left: -20px; 344 | padding: 1px 2px; 345 | opacity: 0; 346 | -webkit-transition: opacity 0.2s linear; 347 | } 348 | .for-h1 .pilcrow { 349 | top: 47px; 350 | } 351 | .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow { 352 | top: 35px; 353 | } 354 | 355 | ul.sections > li > div.annotation:hover .pilcrow { 356 | opacity: 1; 357 | } 358 | } 359 | 360 | /*---------------------- (> 1025px) ---------------------*/ 361 | @media only screen and (min-width: 1025px) { 362 | 363 | body { 364 | font-size: 16px; 365 | line-height: 24px; 366 | } 367 | 368 | #background { 369 | width: 525px; 370 | } 371 | ul.sections > li > div.annotation { 372 | max-width: 525px; 373 | min-width: 525px; 374 | padding: 10px 25px 1px 50px; 375 | } 376 | ul.sections > li > div.content { 377 | padding: 9px 15px 16px 25px; 378 | } 379 | } 380 | 381 | /*---------------------- Syntax Highlighting -----------------------------*/ 382 | 383 | td.linenos { background-color: #f0f0f0; padding-right: 10px; } 384 | span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } 385 | /* 386 | 387 | github.com style (c) Vasily Polovnyov 388 | 389 | */ 390 | 391 | pre code { 392 | display: block; padding: 0.5em; 393 | color: #000; 394 | background: #f8f8ff 395 | } 396 | 397 | pre .hljs-comment, 398 | pre .hljs-template_comment, 399 | pre .hljs-diff .hljs-header, 400 | pre .hljs-javadoc { 401 | color: #408080; 402 | font-style: italic 403 | } 404 | 405 | pre .hljs-keyword, 406 | pre .hljs-assignment, 407 | pre .hljs-literal, 408 | pre .hljs-css .hljs-rule .hljs-keyword, 409 | pre .hljs-winutils, 410 | pre .hljs-javascript .hljs-title, 411 | pre .hljs-lisp .hljs-title, 412 | pre .hljs-subst { 413 | color: #954121; 414 | /*font-weight: bold*/ 415 | } 416 | 417 | pre .hljs-number, 418 | pre .hljs-hexcolor { 419 | color: #40a070 420 | } 421 | 422 | pre .hljs-string, 423 | pre .hljs-tag .hljs-value, 424 | pre .hljs-phpdoc, 425 | pre .hljs-tex .hljs-formula { 426 | color: #219161; 427 | } 428 | 429 | pre .hljs-title, 430 | pre .hljs-id { 431 | color: #19469D; 432 | } 433 | pre .hljs-params { 434 | color: #00F; 435 | } 436 | 437 | pre .hljs-javascript .hljs-title, 438 | pre .hljs-lisp .hljs-title, 439 | pre .hljs-subst { 440 | font-weight: normal 441 | } 442 | 443 | pre .hljs-class .hljs-title, 444 | pre .hljs-haskell .hljs-label, 445 | pre .hljs-tex .hljs-command { 446 | color: #458; 447 | font-weight: bold 448 | } 449 | 450 | pre .hljs-tag, 451 | pre .hljs-tag .hljs-title, 452 | pre .hljs-rules .hljs-property, 453 | pre .hljs-django .hljs-tag .hljs-keyword { 454 | color: #000080; 455 | font-weight: normal 456 | } 457 | 458 | pre .hljs-attribute, 459 | pre .hljs-variable, 460 | pre .hljs-instancevar, 461 | pre .hljs-lisp .hljs-body { 462 | color: #008080 463 | } 464 | 465 | pre .hljs-regexp { 466 | color: #B68 467 | } 468 | 469 | pre .hljs-class { 470 | color: #458; 471 | font-weight: bold 472 | } 473 | 474 | pre .hljs-symbol, 475 | pre .hljs-ruby .hljs-symbol .hljs-string, 476 | pre .hljs-ruby .hljs-symbol .hljs-keyword, 477 | pre .hljs-ruby .hljs-symbol .hljs-keymethods, 478 | pre .hljs-lisp .hljs-keyword, 479 | pre .hljs-tex .hljs-special, 480 | pre .hljs-input_number { 481 | color: #990073 482 | } 483 | 484 | pre .hljs-builtin, 485 | pre .hljs-constructor, 486 | pre .hljs-built_in, 487 | pre .hljs-lisp .hljs-title { 488 | color: #0086b3 489 | } 490 | 491 | pre .hljs-preprocessor, 492 | pre .hljs-pi, 493 | pre .hljs-doctype, 494 | pre .hljs-shebang, 495 | pre .hljs-cdata { 496 | color: #999; 497 | font-weight: bold 498 | } 499 | 500 | pre .hljs-deletion { 501 | background: #fdd 502 | } 503 | 504 | pre .hljs-addition { 505 | background: #dfd 506 | } 507 | 508 | pre .hljs-diff .hljs-change { 509 | background: #0086b3 510 | } 511 | 512 | pre .hljs-chunk { 513 | color: #aaa 514 | } 515 | 516 | pre .hljs-tex .hljs-formula { 517 | opacity: 0.5; 518 | } 519 | -------------------------------------------------------------------------------- /underscore-min.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.8.3 2 | // http://underscorejs.org 3 | // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 4 | // Underscore may be freely distributed under the MIT license. 5 | (function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this); 6 | //# sourceMappingURL=underscore-min.map -------------------------------------------------------------------------------- /test/utility.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var _ = typeof require == 'function' ? require('..') : window._; 3 | var templateSettings; 4 | 5 | QUnit.module('Utility', { 6 | 7 | setup: function() { 8 | templateSettings = _.clone(_.templateSettings); 9 | }, 10 | 11 | teardown: function() { 12 | _.templateSettings = templateSettings; 13 | } 14 | 15 | }); 16 | 17 | test('#750 - Return _ instance.', 2, function() { 18 | var instance = _([]); 19 | ok(_(instance) === instance); 20 | ok(new _(instance) === instance); 21 | }); 22 | 23 | test('identity', function() { 24 | var stooge = {name : 'moe'}; 25 | equal(_.identity(stooge), stooge, 'stooge is the same as his identity'); 26 | }); 27 | 28 | test('constant', function() { 29 | var stooge = {name : 'moe'}; 30 | equal(_.constant(stooge)(), stooge, 'should create a function that returns stooge'); 31 | }); 32 | 33 | test('noop', function() { 34 | strictEqual(_.noop('curly', 'larry', 'moe'), undefined, 'should always return undefined'); 35 | }); 36 | 37 | test('property', function() { 38 | var stooge = {name : 'moe'}; 39 | equal(_.property('name')(stooge), 'moe', 'should return the property with the given name'); 40 | equal(_.property('name')(null), undefined, 'should return undefined for null values'); 41 | equal(_.property('name')(undefined), undefined, 'should return undefined for undefined values'); 42 | }); 43 | 44 | test('propertyOf', function() { 45 | var stoogeRanks = _.propertyOf({curly: 2, moe: 1, larry: 3}); 46 | equal(stoogeRanks('curly'), 2, 'should return the property with the given name'); 47 | equal(stoogeRanks(null), undefined, 'should return undefined for null values'); 48 | equal(stoogeRanks(undefined), undefined, 'should return undefined for undefined values'); 49 | 50 | function MoreStooges() { this.shemp = 87; } 51 | MoreStooges.prototype = {curly: 2, moe: 1, larry: 3}; 52 | var moreStoogeRanks = _.propertyOf(new MoreStooges()); 53 | equal(moreStoogeRanks('curly'), 2, 'should return properties from further up the prototype chain'); 54 | 55 | var nullPropertyOf = _.propertyOf(null); 56 | equal(nullPropertyOf('curly'), undefined, 'should return undefined when obj is null'); 57 | 58 | var undefPropertyOf = _.propertyOf(undefined); 59 | equal(undefPropertyOf('curly'), undefined, 'should return undefined when obj is undefined'); 60 | }); 61 | 62 | test('random', function() { 63 | var array = _.range(1000); 64 | var min = Math.pow(2, 31); 65 | var max = Math.pow(2, 62); 66 | 67 | ok(_.every(array, function() { 68 | return _.random(min, max) >= min; 69 | }), 'should produce a random number greater than or equal to the minimum number'); 70 | 71 | ok(_.some(array, function() { 72 | return _.random(Number.MAX_VALUE) > 0; 73 | }), 'should produce a random number when passed `Number.MAX_VALUE`'); 74 | }); 75 | 76 | test('now', function() { 77 | var diff = _.now() - new Date().getTime(); 78 | ok(diff <= 0 && diff > -5, 'Produces the correct time in milliseconds');//within 5ms 79 | }); 80 | 81 | test('uniqueId', function() { 82 | var ids = [], i = 0; 83 | while (i++ < 100) ids.push(_.uniqueId()); 84 | equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids'); 85 | }); 86 | 87 | test('times', function() { 88 | var vals = []; 89 | _.times(3, function (i) { vals.push(i); }); 90 | deepEqual(vals, [0, 1, 2], 'is 0 indexed'); 91 | // 92 | vals = []; 93 | _(3).times(function(i) { vals.push(i); }); 94 | deepEqual(vals, [0, 1, 2], 'works as a wrapper'); 95 | // collects return values 96 | deepEqual([0, 1, 2], _.times(3, function(i) { return i; }), 'collects return values'); 97 | 98 | deepEqual(_.times(0, _.identity), []); 99 | deepEqual(_.times(-1, _.identity), []); 100 | deepEqual(_.times(parseFloat('-Infinity'), _.identity), []); 101 | }); 102 | 103 | test('mixin', function() { 104 | _.mixin({ 105 | myReverse: function(string) { 106 | return string.split('').reverse().join(''); 107 | } 108 | }); 109 | equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _'); 110 | equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper'); 111 | }); 112 | 113 | test('_.escape', function() { 114 | equal(_.escape(null), ''); 115 | }); 116 | 117 | test('_.unescape', function() { 118 | var string = 'Curly & Moe'; 119 | equal(_.unescape(null), ''); 120 | equal(_.unescape(_.escape(string)), string); 121 | equal(_.unescape(string), string, 'don\'t unescape unnecessarily'); 122 | }); 123 | 124 | // Don't care what they escape them to just that they're escaped and can be unescaped 125 | test('_.escape & unescape', function() { 126 | // test & (&) seperately obviously 127 | var escapeCharacters = ['<', '>', '"', '\'', '`']; 128 | 129 | _.each(escapeCharacters, function(escapeChar) { 130 | var str = 'a ' + escapeChar + ' string escaped'; 131 | var escaped = _.escape(str); 132 | notEqual(str, escaped, escapeChar + ' is escaped'); 133 | equal(str, _.unescape(escaped), escapeChar + ' can be unescaped'); 134 | 135 | str = 'a ' + escapeChar + escapeChar + escapeChar + 'some more string' + escapeChar; 136 | escaped = _.escape(str); 137 | 138 | equal(escaped.indexOf(escapeChar), -1, 'can escape multiple occurances of ' + escapeChar); 139 | equal(_.unescape(escaped), str, 'multiple occurrences of ' + escapeChar + ' can be unescaped'); 140 | }); 141 | 142 | // handles multiple escape characters at once 143 | var joiner = ' other stuff '; 144 | var allEscaped = escapeCharacters.join(joiner); 145 | allEscaped += allEscaped; 146 | ok(_.every(escapeCharacters, function(escapeChar) { 147 | return allEscaped.indexOf(escapeChar) !== -1; 148 | }), 'handles multiple characters'); 149 | ok(allEscaped.indexOf(joiner) >= 0, 'can escape multiple escape characters at the same time'); 150 | 151 | // test & -> & 152 | var str = 'some string & another string & yet another'; 153 | var escaped = _.escape(str); 154 | 155 | ok(escaped.indexOf('&') !== -1, 'handles & aka &'); 156 | equal(_.unescape(str), str, 'can unescape &'); 157 | }); 158 | 159 | test('template', function() { 160 | var basicTemplate = _.template("<%= thing %> is gettin' on my noives!"); 161 | var result = basicTemplate({thing : 'This'}); 162 | equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation'); 163 | 164 | var sansSemicolonTemplate = _.template('A <% this %> B'); 165 | equal(sansSemicolonTemplate(), 'A B'); 166 | 167 | var backslashTemplate = _.template('<%= thing %> is \\ridanculous'); 168 | equal(backslashTemplate({thing: 'This'}), 'This is \\ridanculous'); 169 | 170 | var escapeTemplate = _.template('<%= a ? "checked=\\"checked\\"" : "" %>'); 171 | equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); 172 | 173 | var fancyTemplate = _.template('
    <% ' + 174 | ' for (var key in people) { ' + 175 | '%>
  • <%= people[key] %>
  • <% } %>
'); 176 | result = fancyTemplate({people : {moe : 'Moe', larry : 'Larry', curly : 'Curly'}}); 177 | equal(result, '
  • Moe
  • Larry
  • Curly
', 'can run arbitrary javascript in templates'); 178 | 179 | var escapedCharsInJavascriptTemplate = _.template('
    <% _.each(numbers.split("\\n"), function(item) { %>
  • <%= item %>
  • <% }) %>
'); 180 | result = escapedCharsInJavascriptTemplate({numbers: 'one\ntwo\nthree\nfour'}); 181 | equal(result, '
  • one
  • two
  • three
  • four
', 'Can use escaped characters (e.g. \\n) in JavaScript'); 182 | 183 | var namespaceCollisionTemplate = _.template('<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %>
<% }); %>'); 184 | result = namespaceCollisionTemplate({ 185 | pageCount: 3, 186 | thumbnails: { 187 | 1: 'p1-thumbnail.gif', 188 | 2: 'p2-thumbnail.gif', 189 | 3: 'p3-thumbnail.gif' 190 | } 191 | }); 192 | equal(result, '3 p3-thumbnail.gif
'); 193 | 194 | var noInterpolateTemplate = _.template('

Just some text. Hey, I know this is silly but it aids consistency.

'); 195 | result = noInterpolateTemplate(); 196 | equal(result, '

Just some text. Hey, I know this is silly but it aids consistency.

'); 197 | 198 | var quoteTemplate = _.template("It's its, not it's"); 199 | equal(quoteTemplate({}), "It's its, not it's"); 200 | 201 | var quoteInStatementAndBody = _.template('<% ' + 202 | " if(foo == 'bar'){ " + 203 | "%>Statement quotes and 'quotes'.<% } %>"); 204 | equal(quoteInStatementAndBody({foo: 'bar'}), "Statement quotes and 'quotes'."); 205 | 206 | var withNewlinesAndTabs = _.template('This\n\t\tis: <%= x %>.\n\tok.\nend.'); 207 | equal(withNewlinesAndTabs({x: 'that'}), 'This\n\t\tis: that.\n\tok.\nend.'); 208 | 209 | var template = _.template('<%- value %>'); 210 | result = template({value: '