├── .npmignore ├── .gitignore ├── .travis.yml ├── img └── logo.png ├── dist ├── allthethings.min.js └── allthethings.js ├── package.json ├── lib └── allthethings.js ├── LICENSE-MIT ├── grunt.js ├── test └── allthethings_test.js └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - 0.8 -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/markdalgleish/allthethings.js/master/img/logo.png -------------------------------------------------------------------------------- /dist/allthethings.min.js: -------------------------------------------------------------------------------- 1 | /*! allthethings v0.0.1-alpha-8 | (c) 2012 Mark Dalgleish | https://github.com/markdalgleish/allthethings.js | Licensed MIT */ 2 | (function(e){var t={filter:/^(filter|is)/,reduce:/^(reduce|add|calculate)/,reduceRight:/^(reduce|add|calculate)Right/,some:/^(some|contains|has)/,every:/^(every|all)/},n=function(e,n){var r="_allthethings_func";return e[r]||(e[r]=n[Object.keys(t).reduce(function(n,r){return t[r].test(e.name)?r:n},"map")])},r=function(e){return n(this,e).call(e,this)};["allThe","fromThe","inThe"].forEach(function(e){Function.prototype[e]=r}),e.rules=t})(typeof exports=="object"&&exports||(this.allthethings={})); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "allthethings", 3 | "description": "Let your iterations read like actual sentences.", 4 | "version": "0.0.1-alpha-8", 5 | "homepage": "https://github.com/markdalgleish/allthethings.js", 6 | "author": { 7 | "name": "Mark Dalgleish", 8 | "url": "http://markdalgleish.com" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/markdalgleish/allthethings.js.git" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/markdalgleish/allthethings.js/issues" 16 | }, 17 | "licenses": [ 18 | { 19 | "type": "MIT", 20 | "url": "http://mit-license.org/markdalgleish" 21 | } 22 | ], 23 | "main": "lib/allthethings", 24 | "engines": { 25 | "node": "*" 26 | }, 27 | "scripts": { 28 | "test": "grunt test" 29 | }, 30 | "devDependencies": { 31 | "grunt": "~0.3.17" 32 | }, 33 | "keywords": [] 34 | } -------------------------------------------------------------------------------- /lib/allthethings.js: -------------------------------------------------------------------------------- 1 | (function(exports) { 2 | 3 | var rules = { 4 | filter: /^(filter|is)/, 5 | reduce: /^(reduce|add|calculate)/, 6 | reduceRight: /^(reduce|add|calculate)Right/, 7 | some: /^(some|contains|has)/, 8 | every: /^(every|all)/ 9 | }, 10 | 11 | resolveFunc = function(caller, things) { 12 | var cachedFuncKey = '_allthethings_func'; 13 | return caller[cachedFuncKey] || (caller[cachedFuncKey] = 14 | things[Object.keys(rules).reduce(function(prevKey, key) { 15 | return rules[key].test(caller.name) ? key : prevKey; 16 | }, 'map')] 17 | ); 18 | }, 19 | 20 | allthethings = function(things) { 21 | return resolveFunc(this, things).call(things, this); 22 | }; 23 | 24 | ['allThe', 'fromThe', 'inThe'].forEach(function(alias) { 25 | Function.prototype[alias] = allthethings; 26 | }); 27 | 28 | exports.rules = rules; 29 | 30 | }(typeof exports === 'object' && exports || (this.allthethings = {}))); 31 | -------------------------------------------------------------------------------- /dist/allthethings.js: -------------------------------------------------------------------------------- 1 | /*! allthethings v0.0.1-alpha-8 2 | * https://github.com/markdalgleish/allthethings.js 3 | * Copyright (c) 2012 Mark Dalgleish; Licensed MIT */ 4 | 5 | (function(exports) { 6 | 7 | var rules = { 8 | filter: /^(filter|is)/, 9 | reduce: /^(reduce|add|calculate)/, 10 | reduceRight: /^(reduce|add|calculate)Right/, 11 | some: /^(some|contains|has)/, 12 | every: /^(every|all)/ 13 | }, 14 | 15 | resolveFunc = function(caller, things) { 16 | var cachedFuncKey = '_allthethings_func'; 17 | return caller[cachedFuncKey] || (caller[cachedFuncKey] = 18 | things[Object.keys(rules).reduce(function(prevKey, key) { 19 | return rules[key].test(caller.name) ? key : prevKey; 20 | }, 'map')] 21 | ); 22 | }, 23 | 24 | allthethings = function(things) { 25 | return resolveFunc(this, things).call(things, this); 26 | }; 27 | 28 | ['allThe', 'fromThe', 'inThe'].forEach(function(alias) { 29 | Function.prototype[alias] = allthethings; 30 | }); 31 | 32 | exports.rules = rules; 33 | 34 | }(typeof exports === 'object' && exports || (this.allthethings = {}))); 35 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Mark Dalgleish 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /grunt.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | // Project configuration. 4 | grunt.initConfig({ 5 | pkg: '', 6 | meta: { 7 | banner: '/*! <%= pkg.name %> v<%= pkg.version %>\n' + 8 | '<%= pkg.homepage ? " * " + pkg.homepage + "\n" : "" %>' + 9 | ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + 10 | ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */', 11 | microbanner: '/*! <%= pkg.title || pkg.name %> v<%= pkg.version %> | ' + 12 | '(c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %> | ' + 13 | '<%= pkg.homepage ? pkg.homepage + " | " : "" %>' + 14 | 'Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */' 15 | }, 16 | concat: { 17 | dist: { 18 | src: ['', '.js>'], 19 | dest: 'dist/<%= pkg.name %>.js' 20 | } 21 | }, 22 | min: { 23 | dist: { 24 | src: ['', ''], 25 | dest: 'dist/<%= pkg.name %>.min.js' 26 | } 27 | }, 28 | test: { 29 | files: ['test/**/*.js'] 30 | }, 31 | lint: { 32 | files: ['grunt.js', 'lib/**/*.js', 'test/**/*.js'] 33 | }, 34 | watch: { 35 | files: '', 36 | tasks: 'lint test' 37 | }, 38 | jshint: { 39 | options: { 40 | curly: true, 41 | eqeqeq: true, 42 | immed: true, 43 | latedef: true, 44 | newcap: true, 45 | noarg: true, 46 | sub: true, 47 | undef: true, 48 | boss: true, 49 | eqnull: true 50 | }, 51 | globals: { 52 | exports: true, 53 | module: false 54 | } 55 | }, 56 | uglify: {} 57 | }); 58 | 59 | // Default task. 60 | grunt.registerTask('default', 'lint test concat min'); 61 | 62 | }; 63 | -------------------------------------------------------------------------------- /test/allthethings_test.js: -------------------------------------------------------------------------------- 1 | /*global require:true */ 2 | var allthethings = require('../lib/allthethings.js'); 3 | 4 | exports['ALL THE THINGS'] = { 5 | 'forEach': function(test) { 6 | var total = 0, 7 | numbers = [1,2,3]; 8 | 9 | function incrementTotalWith(number) { 10 | total += number; 11 | } 12 | 13 | incrementTotalWith.allThe(numbers); 14 | 15 | test.deepEqual(total, 6); 16 | test.done(); 17 | }, 18 | 19 | 'map': function(test) { 20 | var numbers = [1,2,3]; 21 | 22 | function double (number) { 23 | return number * 2; 24 | } 25 | 26 | test.deepEqual(double.allThe(numbers), [2,4,6]); 27 | test.done(); 28 | }, 29 | 30 | 'filter': function(test) { 31 | var numbers = [1,2,3,4]; 32 | 33 | function filterOddNumbers(number) { 34 | return number % 2 === 0; 35 | } 36 | 37 | function isEven(number) { 38 | return number % 2 === 0; 39 | } 40 | 41 | test.deepEqual(filterOddNumbers.fromThe(numbers), [2,4]); 42 | test.deepEqual(isEven.fromThe(numbers), [2,4]); 43 | test.done(); 44 | }, 45 | 46 | 'reduce': function(test) { 47 | var numbers = [1,2,3]; 48 | 49 | function reduceTotal(a, b) { 50 | return a + b; 51 | } 52 | 53 | function calculateTotal(a, b) { 54 | return a + b; 55 | } 56 | 57 | function addTotal(a, b) { 58 | return a + b; 59 | } 60 | 61 | test.equal(reduceTotal.fromThe(numbers), 6); 62 | test.equal(calculateTotal.fromThe(numbers), 6); 63 | test.equal(addTotal.fromThe(numbers), 6); 64 | test.done(); 65 | }, 66 | 67 | 'reduceRight': function(test) { 68 | var numbers = [1,2,3]; 69 | 70 | function reduceRightTest(a, b) { 71 | return b; 72 | } 73 | 74 | function calculateRightTest(a, b) { 75 | return b; 76 | } 77 | 78 | function addRightTest(a, b) { 79 | return b; 80 | } 81 | 82 | test.equal(reduceRightTest.fromThe(numbers), 1); 83 | test.equal(calculateRightTest.fromThe(numbers), 1); 84 | test.equal(addRightTest.fromThe(numbers), 1); 85 | test.done(); 86 | }, 87 | 88 | 'some': function(test) { 89 | var numbers = [-1,0,1], 90 | positiveNumbers = [1,2,3]; 91 | 92 | function someNegatives(number) { 93 | return number < 0; 94 | } 95 | 96 | function containsNegatives(number) { 97 | return number < 0; 98 | } 99 | 100 | function hasNegatives(number) { 101 | return number < 0; 102 | } 103 | 104 | test.strictEqual(someNegatives.inThe(numbers), true); 105 | test.strictEqual(someNegatives.inThe(positiveNumbers), false); 106 | 107 | test.strictEqual(containsNegatives.inThe(numbers), true); 108 | test.strictEqual(containsNegatives.inThe(positiveNumbers), false); 109 | 110 | test.strictEqual(hasNegatives.inThe(numbers), true); 111 | test.strictEqual(hasNegatives.inThe(positiveNumbers), false); 112 | 113 | test.done(); 114 | }, 115 | 116 | 'every': function(test) { 117 | var numbers = [-1,0,1], 118 | negativeNumbers = [-1,-2,-3]; 119 | 120 | function everyNumberIsNegative(number) { 121 | return number < 0; 122 | } 123 | 124 | function allNegatives(number) { 125 | return number < 0; 126 | } 127 | 128 | test.strictEqual(everyNumberIsNegative.inThe(negativeNumbers), true); 129 | test.strictEqual(everyNumberIsNegative.inThe(numbers), false); 130 | 131 | test.strictEqual(allNegatives.inThe(negativeNumbers), true); 132 | test.strictEqual(allNegatives.inThe(numbers), false); 133 | 134 | test.done(); 135 | }, 136 | 137 | 'custom rules': function(test) { 138 | allthethings.rules.filter = /foobar/; 139 | 140 | var numbers = [1,2,3,4]; 141 | 142 | function foobar(number) { 143 | return number % 2 === 0; 144 | } 145 | 146 | test.deepEqual(foobar.fromThe(numbers), [2,4]); 147 | test.done(); 148 | } 149 | }; 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://secure.travis-ci.org/markdalgleish/allthethings.js.png)](http://travis-ci.org/markdalgleish/allthethings.js) 2 | 3 | # ALLTHETHINGS.JS 4 | 5 | ![ALLTHETHINGS.JS](https://raw.github.com/markdalgleish/allthethings.js/master/img/logo.png) 6 | 7 | ### Let your array iterations read like actual sentences: 8 | 9 | ``` js 10 | var things = ['all', 'the', 'things']; 11 | 12 | function log(thing) { 13 | console.log(thing); 14 | } 15 | 16 | log.allThe(things); 17 | ``` 18 | 19 | For no extra cost, you also get the 'fromThe' and 'inThe' aliases, for your grammatical needs: 20 | 21 | ``` js 22 | var proHackers = filterNoobs.fromThe(hackers); 23 | ``` 24 | 25 | ``` js 26 | containsProHackers.inThe(hackers); // true 27 | ``` 28 | 29 | And all for less than 1KB, with no dependencies*. Delicious. 30 | 31 | *Unless your browser is an antique. Then you need [es5-shim](https://github.com/kriskowal/es5-shim). 32 | 33 | ALLTHETHINGS.JS allows you to *sentencify* the following array methods: 34 | 35 | - [forEach](#foreach--map) 36 | - [map](#foreach--map) 37 | - [filter](#filter) 38 | - [reduce](#reduce--reduceright) 39 | - [reduceRight](#reduce--reduceright) 40 | - [some](#some) 41 | - [every](#every) 42 | 43 | ### Gimme gimme 44 | 45 | #### Node.js 46 | 47 | Install with: `npm install allthethings` 48 | 49 | ```javascript 50 | require('allthethings'); 51 | ``` 52 | 53 | #### Browser 54 | 55 | Download the [production version][min] or the [development version][max]. 56 | 57 | [min]: https://raw.github.com/markdalgleish/allthethings.js/master/dist/allthethings.min.js 58 | [max]: https://raw.github.com/markdalgleish/allthethings.js/master/dist/allthethings.js 59 | 60 | ## forEach / map 61 | 62 | By default, 'allThe' performs a [*map*](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map) on the array, which doubles as a [*forEach*](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach): 63 | 64 | ### forEach 65 | 66 | ```js 67 | var things = ['all', 'the', 'things']; 68 | 69 | function log(thing) { 70 | console.log(thing); 71 | } 72 | 73 | log.allThe(things); 74 | ``` 75 | 76 | ### map 77 | 78 | ```js 79 | var numbers = [1,2,3]; 80 | 81 | function triple(number) { 82 | return number * 3; 83 | } 84 | 85 | var multiplesOfThree = triple.allThe(numbers); // [3,6,9] 86 | ``` 87 | 88 | ## filter 89 | 90 | If your named function starts with 'filter' or 'is', then a [*filter*](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter) is performed. 91 | 92 | When filtering, it's idiomatic to use 'fromThe' instead of 'allThe': 93 | 94 | ```js 95 | var numbers = [-2,-1,0,1,2]; 96 | 97 | function filterNegatives(number) { 98 | return number >= 0; 99 | } 100 | 101 | filterNegatives.fromThe(numbers); // [0,1,2] 102 | ``` 103 | 104 | ```js 105 | var numbers = [-2,-1,0,1,2]; 106 | 107 | function isPositive(number) { 108 | return number > 0; 109 | } 110 | 111 | isPositive.fromThe(numbers); // [1,2] 112 | ``` 113 | 114 | ## reduce / reduceRight 115 | 116 | If your named function starts with 'reduce', 'calculate' or 'add', then a [*reduce*](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/Reduce) is performed. 117 | 118 | If you add 'Right' to any of these, then a [*reduceRight*](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/ReduceRight) is performed instead. 119 | 120 | When reducing, it's idiomatic to use 'fromThe' instead of 'allThe': 121 | 122 | Given the 'numbers' array: 123 | 124 | ``` js 125 | var numbers = [1,2,3]; 126 | ``` 127 | 128 | Any of these will work identically: 129 | 130 | ```js 131 | function reduceTotal(a, b) { 132 | return a + b; 133 | } 134 | 135 | var total = reduceTotal.fromThe(numbers); // 6 136 | ``` 137 | 138 | ```js 139 | function calculateTotal(a, b) { 140 | return a + b; 141 | } 142 | 143 | var total = calculateTotal.fromThe(numbers); // 6 144 | ``` 145 | 146 | ```js 147 | function addTotal(a, b) { 148 | return a + b; 149 | } 150 | 151 | var total = addTotal.fromThe(numbers); // 6 152 | ``` 153 | 154 | ## some 155 | 156 | If your named function starts with 'some', 'contains' or 'has', then a [*some*](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/some) is performed. 157 | 158 | When using 'some', it's idiomatic to use 'inThe' instead of 'allThe': 159 | 160 | ```js 161 | var numbers = [-2,-1,0,1,2]; 162 | 163 | function someNegatives(number) { 164 | return number < 0; 165 | } 166 | 167 | someNegatives.inThe(numbers); // true 168 | ``` 169 | 170 | ```js 171 | var numbers = [-2,-1,0,1,2]; 172 | 173 | function containsNegatives(number) { 174 | return number < 0; 175 | } 176 | 177 | containsNegatives.inThe(numbers); // true 178 | ``` 179 | 180 | ```js 181 | var numbers = [-2,-1,0,1,2]; 182 | 183 | function hasNegatives(number) { 184 | return number < 0; 185 | } 186 | 187 | hasNegatives.inThe(numbers); // true 188 | ``` 189 | 190 | ## every 191 | 192 | If your named function starts with 'every' or 'all', then an [*every*](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/every) is performed. 193 | 194 | When using 'every', it's idiomatic to use 'inThe' instead of 'allThe': 195 | 196 | ```js 197 | var numbers = [1,2,3,4,5]; 198 | 199 | function everyNumberIsPositive(number) { 200 | return number > 0; 201 | } 202 | 203 | everyNumberIsPositive.inThe(numbers); // true 204 | ``` 205 | 206 | ```js 207 | var numbers = [1,2,3,4,5]; 208 | 209 | function allPositive(number) { 210 | return number > 0; 211 | } 212 | 213 | allPositive.inThe(numbers); // true 214 | ``` 215 | 216 | ## Elite hacker tips 217 | 218 | ### Aliased functions 219 | 220 | Assign a named function expression to a variable of a different name: 221 | 222 | ``` js 223 | var things = [false, true, false]; 224 | 225 | var myAliasedFunction = function filter(thing) { 226 | return thing === true; 227 | }; 228 | 229 | myAliasedFunction.allThe(things); // [true] 230 | ``` 231 | 232 | ### Custom function name rules 233 | 234 | You can create new rules or override existing ones: 235 | 236 | #### In Node.js 237 | 238 | ``` js 239 | var allthethings = require('allthethings'); 240 | 241 | allthethings.rules.filter = /foobar/; 242 | ``` 243 | 244 | #### In the browser 245 | 246 | ``` js 247 | window.allthethings.rules.filter = /foobar/; 248 | ``` 249 | 250 | #### Which allows: 251 | 252 | ``` js 253 | var numbers = [1,2,3,4]; 254 | 255 | function foobar(number) { 256 | return number % 2 === 0; 257 | } 258 | 259 | // This now performs a filter: 260 | foobar.allThe(numbers); // [2,4] 261 | ``` 262 | 263 | ## Contributing 264 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [grunt](http://gruntjs.com/). 265 | 266 | ## License 267 | Copyright (c) 2012 Mark Dalgleish 268 | Licensed under the MIT license. 269 | --------------------------------------------------------------------------------