├── .gitignore ├── Makefile ├── Readme.md ├── component.json ├── index.js └── test └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | components 3 | build -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | build: components index.js 3 | @component build 4 | 5 | components: component.json 6 | @component install --dev 7 | 8 | clean: 9 | rm -fr build components 10 | 11 | .PHONY: clean 12 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | # Natural sort algorithm with unicode support 4 | 5 | The algorithm is written by [Jim Palmer](http://www.linkedin.com/in/jimbob) 6 | and found at [http://www.overset.com/2008/09/01/javascript-natural-sort-algorithm/](http://www.overset.com/2008/09/01/javascript-natural-sort-algorithm/). 7 | 8 | I, [javve](http://github.com/javve), only put it into a Component. 9 | 10 | ## Installation 11 | 12 | $ component install javve/natural-sort 13 | 14 | ## Example 15 | 16 | ```js 17 | var naturalSort = require('natural-sort'); 18 | 19 | var values = ['B', 'a', 'D', 'c']; 20 | 21 | values.sort(naturalSort); // ['B', 'D', 'a', 'c'] 22 | 23 | values.sort(function(a, b) { 24 | return naturalSort(a, b, { insensitive: true }); 25 | }); // ['a', 'B', 'c', 'D'] 26 | 27 | values.sort(function(a, b) { 28 | return naturalSort(a, b, { insensitive: true, desc: true }) 29 | }); // ['D', 'c', 'B', 'a'] 30 | 31 | 32 | var values = [ 33 | { val: 'B' }, 34 | { val: 'a' }, 35 | { val: 'D' }, 36 | { val: 'c' } 37 | ]; 38 | 39 | values.sort(function(a, b) { 40 | return naturalSort(a.val, b.val, { insensitive: true }); 41 | }); // ['a', 'B', 'c', 'D'] 42 | 43 | ``` 44 | 45 | Find more examples at [http://www.overset.com/2008/09/01/javascript-natural-sort-algorithm/](http://www.overset.com/2008/09/01/javascript-natural-sort-algorithm/) 46 | or look at the tests in `/test`. It's quite impressive. Handles dates, etc. 47 | 48 | ## License 49 | 50 | MIT 51 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "natural-sort", 3 | "repo": "javve/natural-sort", 4 | "description": "Natural sort algorithm with unicode support", 5 | "version": "1.0.0", 6 | "keywords": ["natural sort", "sort", "unicode", "dates"], 7 | "scripts": [ 8 | "index.js" 9 | ], 10 | "twitter": "@javve", 11 | "license": "MIT" 12 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license 3 | * Author: Jim Palmer (based on chunking idea from Dave Koelle) 4 | */ 5 | 6 | module.exports = function(a, b, options) { 7 | var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi, 8 | sre = /(^[ ]*|[ ]*$)/g, 9 | dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, 10 | hre = /^0x[0-9a-f]+$/i, 11 | ore = /^0/, 12 | options = options || {}, 13 | i = function(s) { return options.insensitive && (''+s).toLowerCase() || ''+s }, 14 | // convert all to strings strip whitespace 15 | x = i(a).replace(sre, '') || '', 16 | y = i(b).replace(sre, '') || '', 17 | // chunk/tokenize 18 | xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), 19 | yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), 20 | // numeric, hex or date detection 21 | xD = parseInt(x.match(hre)) || (xN.length !== 1 && x.match(dre) && Date.parse(x)), 22 | yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null, 23 | oFxNcL, oFyNcL, 24 | mult = options.desc ? -1 : 1; 25 | // first try and sort Hex codes or Dates 26 | if (yD) 27 | if ( xD < yD ) return -1 * mult; 28 | else if ( xD > yD ) return 1 * mult; 29 | // natural sorting through split numeric strings and default strings 30 | for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { 31 | // find floats not starting with '0', string or 0 if not defined (Clint Priest) 32 | oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0; 33 | oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0; 34 | // handle numeric vs string comparison - number < string - (Kyle Adams) 35 | if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL) ? 1 : -1) * mult; } 36 | // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' 37 | else if (typeof oFxNcL !== typeof oFyNcL) { 38 | oFxNcL += ''; 39 | oFyNcL += ''; 40 | } 41 | if (oFxNcL < oFyNcL) return -1 * mult; 42 | if (oFxNcL > oFyNcL) return 1 * mult; 43 | } 44 | return 0; 45 | }; 46 | 47 | /* 48 | var defaultSort = getSortFunction(); 49 | 50 | module.exports = function(a, b, options) { 51 | if (arguments.length == 1) { 52 | options = a; 53 | return getSortFunction(options); 54 | } else { 55 | return defaultSort(a,b); 56 | } 57 | } 58 | */ 59 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |