├── .circleci └── config.yml ├── .eslintrc ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bower.json ├── examples ├── basic.html ├── colspan.html ├── complex.html ├── large-table.html ├── multicolumn-sort.html └── with-settings.html ├── package-lock.json ├── package.json ├── stupidtable.js ├── stupidtable.min.js └── tests ├── jquery.js ├── qunit.css ├── qunit.js ├── test-min.html ├── test.html ├── tests.js └── underscore.js /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | # specify the version you desire here 6 | # - image: selenium/standalone-firefox 7 | - image: joequery/qunit-selenium 8 | 9 | steps: 10 | - checkout 11 | - run: 12 | name: Run local http server 13 | command: ruby -run -e httpd . -p 8080 14 | background: true 15 | - run: 16 | name: Run virtual frame buffer 17 | command: Xvfb :10 -ac 18 | background: true 19 | - run: 20 | name: Sleep 5 21 | command: sleep 5 22 | - run: 23 | name: Run QUnit tests 24 | command: | 25 | export DISPLAY=:10 26 | qunit-selenium --timeout 30 http://localhost:8080/tests/test.html 27 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true 4 | }, 5 | "extends": [ 6 | "eslint:recommended" 7 | ], 8 | "rules": { 9 | "no-unused-vars": ["error", {"args": "none"}] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /q 3 | /minify.js 4 | /stupidtable.min.js 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | v1.1.3 (Released 10/12/2017) 2 | ---------------------------- 3 | 4 | Added npm support 5 | 6 | v1.1.2 (Released 07/11/2017) 7 | ---------------------------- 8 | 9 | Added multicolumn sort capabilities. See [examples/multicolumn-sort.html](https://rawgit.com/joequery/Stupid-Table-Plugin/master/examples/multicolumn-sort.html). 10 | 11 | v1.1.1 (Released 07/02/2017) 12 | ---------------------------- 13 | 14 | Updated internal representation of tables. 15 | Added `will_manually_build_table` setting. 16 | 17 | v1.1.0 (Released 06/28/2017) 18 | ---------------------------- 19 | 20 | We are introducing an implementation of settings for StupidTable. The first 21 | setting is `should_redraw`. This setting allows you to specify a function that 22 | can conditionally prevent the table from redrawing after a sort. 23 | 24 | v1.0.7 (Released 06/25/2017) 25 | ---------------------------- 26 | 27 | A `` element can now be provided with a `data-sort-onload=yes` attribute. 28 | Once `$table.stupidtable()` is called the table will immediately be sorted by 29 | the column with the `data-sort-onload=yes` attribute if one is found. 30 | Resolves [Issue #180](https://github.com/joequery/Stupid-Table-Plugin/issues/180) and [Issue #126](https://github.com/joequery/Stupid-Table-Plugin/issues/126). 31 | 32 | v1.0.6 (Released 06/24/2017) 33 | ---------------------------- 34 | 35 | Fixed [Issue #183](https://github.com/joequery/Stupid-Table-Plugin/issues/183) 36 | that prevented consecutive calls to `$th.stupidsort()` from running when the 37 | same sort direction was specified. 38 | 39 | v1.0.5 (Released 06/10/2017) 40 | ---------------------------- 41 | 42 | before/aftertablesort callbacks can access the column header element via `data.$th`. 43 | 44 | v1.0.4 (Released 06/10/2017) 45 | ---------------------------- 46 | 47 | Force a stable sort to circumvent [unstable sorting implementations](https://stackoverflow.com/questions/3026281/array-sort-sorting-stability-in-different-browsers). 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Joseph McCullough 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Stupid jQuery Table Sort 2 | ======================== 3 | 4 | This is a stupid jQuery table sorting plugin. Nothing fancy, nothing really 5 | impressive. Overall, stupidly simple. Requires jQuery 1.7 or newer. 6 | 7 | [View the demo here][0] 8 | 9 | See the examples directory. 10 | 11 | Installation via [npm][2] 12 | ------------------------- 13 | 14 | $ npm i stupid-table-plugin 15 | 16 | Installation via Bower 17 | ---------------------- 18 | 19 | $ bower install jquery-stupid-table 20 | 21 | 22 | Example Usage 23 | ------------- 24 | 25 | The JS: 26 | 27 | $("table").stupidtable(); 28 | 29 | The HTML: 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ... 46 | ... 47 | ... 48 | 49 | The thead and tbody tags must be used. 50 | 51 | Add a `data-sort` attribute of "DATATYPE" to the th elements to make them sortable 52 | by that data type. If you don't want that column to be sortable, just omit the 53 | `data-sort` attribute. 54 | 55 | 56 | Predefined data types 57 | --------------------- 58 | 59 | Our aim is to keep this plugin as lightweight as possible. Consequently, the 60 | only predefined datatypes that you can pass to the th elements are 61 | 62 | * `int` 63 | * `float` 64 | * `string` (case-sensitive) 65 | * `string-ins` (case-insensitive) 66 | 67 | These data types will be sufficient for many simple tables. However, if you need 68 | different data types for sorting, you can easily create your own! 69 | 70 | Data with multiple representations/predefined order 71 | --------------------------------------------------- 72 | 73 | Stupid Table lets you sort a column by computer friendly values while displaying 74 | human friendly values via the `data-sort-value` attribute on a td element. For 75 | example, to sort timestamps (computer friendly) but display pretty formated 76 | dates (human friendly) 77 | 78 |
intfloatstring
15-.18banana
79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | ... 95 | ... 96 | ... 97 | 98 | In this example, Stupid Table will sort the Birthday column by the timestamps 99 | provided in the `data-sort-value` attributes of the corresponding tds. Since 100 | timestamps are integers, and that's what we're sorting the column by, we specify 101 | the Birthday column as an `int` column in the `data-sort` value of the column 102 | header. 103 | 104 | 105 | Default sorting direction 106 | ------------------------- 107 | 108 | By default, columns will sort ascending. You can specify a column to sort "asc" 109 | or "desc" first. 110 | 111 |
NameBirthday
Joe McCulloughApril 25, 1991
Clint DempseyMarch 9, 1983
112 | 113 | 114 | 115 | ... 116 | 117 | 118 |
float
119 | 120 | Sorting a column on load 121 | ------------------------ 122 | 123 | If you want a specific column to be sorted immediately after 124 | `$table.stupidtable()` is called, you can provide a `data-sort-onload=yes` 125 | attribute. 126 | 127 | 128 | 129 | 130 | 131 | ... 132 | 133 | 134 |
float
135 | 136 | Multicolumn sorting 137 | ------------------- 138 | 139 | A multicolumn sort allows you to define secondary columns to sort by in the 140 | event of a tie with two elements in the sorted column. See [examples/multicolumn-sort.html](https://rawgit.com/joequery/Stupid-Table-Plugin/master/examples/multicolumn-sort.html). 141 | Specify a comma-separated list of th identifiers in a `data-sort-multicolumn` 142 | attribute on a `` element. An identifier can be an integer (which represents 143 | the index of the th element of the multicolumn target) or a string (which 144 | represents the id of the th element of the multicolumn target). 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | Sorting a column programatically 167 | -------------------------------- 168 | 169 | After you have called `$("#mytable").stupidtable()`, if you wish to sort a 170 | column without requiring the user to click on it, select the column th and call 171 | 172 | 173 | var $table = $("#mytable").stupidtable(); 174 | var $th_to_sort = $table.find("thead th").eq(0); 175 | $th_to_sort.stupidsort(); 176 | 177 | // You can also force a direction. 178 | $th_to_sort.stupidsort('asc'); 179 | $th_to_sort.stupidsort('desc'); 180 | 181 | Updating a table cell's value 182 | ----------------------------- 183 | 184 | If you wish for Stupid Table to respond to changes in the table cell values, you 185 | must explicitely inform Stupid Table to update its cache with the new values. If 186 | you update the table display/sort values without using this mechanism, your 187 | newly updated table **will not sort correctly!** 188 | 189 | /* 190 | * Suppose $age_td is some td in a table under a column specified as an int 191 | * column. stupidtable() must already be called for this table. 192 | */ 193 | $age_td.updateSortVal(23); 194 | 195 | Note that this only changes the internal sort value (whether you specified a 196 | `data-sort-value` or not). Use the standard jQuery `.text()` / `.html()` methods 197 | if you wish to change the display values. 198 | 199 | 200 | Callbacks 201 | --------- 202 | 203 | To execute a callback function after a table column has been sorted, you can 204 | bind on `aftertablesort`. 205 | 206 | var table = $("table").stupidtable(); 207 | table.bind('aftertablesort', function (event, data) { 208 | // data.column - the index of the column sorted after a click 209 | // data.direction - the sorting direction (either asc or desc) 210 | // data.$th - the th element (in jQuery wrapper) 211 | // $(this) - this table object 212 | 213 | console.log("The sorting direction: " + data.direction); 214 | console.log("The column index: " + data.column); 215 | }); 216 | 217 | Similarly, to execute a callback before a table column has been sorted, you can 218 | bind on `beforetablesort`. 219 | 220 | See the complex_example.html file. 221 | 222 | Creating your own data types 223 | ---------------------------- 224 | 225 | Sometimes you don't have control over the HTML produced by the backend. In the 226 | event you need to sort complex data without a `data-sort-value` attribute, you 227 | can create your own data type. Creating your own data type for sorting purposes 228 | is easy as long as you are comfortable using custom functions for sorting. 229 | Consult [Mozilla's Docs][1] if you're not. 230 | 231 | Let's create an alphanum datatype for a User ID that takes strings in the form 232 | "D10", "A40", and sorts the column based on the numbers in the string. 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | ... 253 | ... 254 | ... 255 | 256 | Now we need to specify how the **alphanum** type will be sorted. To do that, 257 | we do the following: 258 | 259 | $("table").stupidtable({ 260 | "alphanum":function(a,b){ 261 | 262 | var pattern = "^[A-Z](\\d+)$"; 263 | var re = new RegExp(pattern); 264 | 265 | var aNum = re.exec(a).slice(1); 266 | var bNum = re.exec(b).slice(1); 267 | 268 | return parseInt(aNum,10) - parseInt(bNum,10); 269 | } 270 | }); 271 | 272 | This extracts the integers from the cell and compares them in the style 273 | that sort functions use. 274 | 275 | StupidTable Settings 276 | -------------------- 277 | 278 | As of 1.1.0 settings have been introduced. Settings are defined like so: 279 | 280 | var $table = $("#mytable"); 281 | $table.stupidtable_settings({ 282 | // Settings for this table specified here 283 | }); 284 | $table.stupidtable(); 285 | 286 | Listed below are the available settings. 287 | 288 | ### will_manually_build_table 289 | 290 | (Introduced in verison 1.1.1) 291 | 292 | Options: 293 | 294 | * `true` 295 | * `false` (default) 296 | 297 | By default, every time a column is sorted, stupidtable reads the DOM to extract 298 | all the values from the table. For tables that will not change or for very large 299 | tables, this behavior may be suboptimal. To modify this behavior, set the 300 | `will_manually_build_table` setting to `true`. However, you will be responsible 301 | for informing stupidtable that the table has been modified by calling 302 | `$table.stupidtable_build()`. 303 | 304 | var $table = $("#mytable"); 305 | $table.stupidtable_settings({ 306 | will_manually_build_table: true 307 | }); 308 | $table.stupidtable(); 309 | 310 | // Make some modification to the table, such as deleting a row 311 | ... 312 | ... 313 | 314 | // Since will_manually_build_table is true, we must build the table in order 315 | // for future sorts to properly handle our modifications. 316 | $table.stupidtable_build(); 317 | 318 | ### should_redraw 319 | 320 | (Introduced in verison 1.1.0) 321 | 322 | The `should_redraw` setting allows you to specify a function that determines 323 | whether or not the table should be redrawn after it has been internally sorted. 324 | 325 | The `should_redraw` function takes a `sort_info` object as an argument. The 326 | object keys available are: 327 | 328 | * `column` - An array representing the sorted column. Each element of the array is of the form `[sort_val, $tr, index]` 329 | * `sort_dir` - `"asc"` or `"desc"` 330 | * `$th` - The jquery object of the `
intfloatstring
110.0a
110.0a
NameAgeUserID
Joseph McCullough20D10
Justin Edwards29A40
` element that was clicked 331 | * `th_index` - The index of the `` element that was cliked 332 | * `$table` - The jquery object of the `` that contains the `
` that was clicked 333 | * `datatype` - The datatype of the column 334 | * `compare_fn` - The sort/compare function associated with the `` clicked. 335 | 336 | **Example**: If you want to prevent stupidtable from redrawing the table if the 337 | column sorted has all identical values, you would do the following: 338 | 339 | var $table = $("#mytable"); 340 | $table.stupidtable_settings({ 341 | should_redraw: function(sort_info){ 342 | var sorted_column = sort_info.column; 343 | var first_val = sorted_column[0]; 344 | var last_val = sorted_column[sorted_column.length - 1][0]; 345 | 346 | // If first and last element of the sorted column are the same, we 347 | // can assume all elements are the same. 348 | return sort_info.compare_fn(first_val, last_val) !== 0; 349 | } 350 | }); 351 | $table.stupidtable(); 352 | 353 | License 354 | ------- 355 | 356 | The Stupid jQuery Plugin is licensed under the MIT license. See the LICENSE 357 | file for full details. 358 | 359 | Tests 360 | ----- 361 | 362 | Visit `tests/test.html` in your browser to run the QUnit tests. 363 | 364 | 365 | [0]: http://joequery.github.io/Stupid-Table-Plugin/ 366 | [1]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort 367 | [2]: https://www.npmjs.com/package/stupid-table-plugin 368 | 369 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-stupid-table", 3 | "version": "1.1.3", 4 | "homepage": "https://github.com/joequery/Stupid-Table-Plugin", 5 | "authors": [ 6 | "Joseph McCullough" 7 | ], 8 | "description": "A stupidly small and simple jQuery table sorter plugin", 9 | "main": "stupidtable.js", 10 | "dependencies": { 11 | "jquery": ">= 1.7.0" 12 | }, 13 | "keywords": [ 14 | "jquery", 15 | "table", 16 | "sort" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "tests" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /examples/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Stupid jQuery table sort 5 | 6 | 7 | 12 | 30 | 31 | 32 | 33 | 34 | 35 |

Stupid jQuery table sort!

36 | 37 |

This example shows how a sortable table can be implemented with very little configuration. Simply specify the data type on a <th> element using the data-sort attribute, and the plugin handles the rest.

38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
intfloatstring
15-.18banana
9536coke
2-152.5apple
-5388.5zebra
195-858orange
75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /examples/colspan.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Stupid jQuery table sort (colspan test) 5 | 6 | 7 | 12 | 30 | 31 | 32 | 33 | 34 | 35 |

Stupid jQuery table sort! (colspan test)

36 | 37 |

Tables using colspans are handled just fine.

38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 47 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
The Big Table Header
Letter 46 | colspan=2Number 48 |
defX91
abcZ82
bcdY70
71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /examples/complex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Stupid jQuery table sort (complex example) 5 | 6 | 7 | 84 | 105 | 106 | 107 | 108 | 109 |

Stupid jQuery table sort! (complex example)

110 | 111 |

This example showcases several of the more advanced features, including specifying sort values, custom data types and callbacks. View the source of this file or see the documentation for more details on how to implement them.

112 | 113 |

 

114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 |
intintfloatstringcaseCan't sort me!dateLetter frequency
1515-.18bananaHomerarbitrarySep 15, 2002E
959536purplepointlessAug 07, 2004T
22-152.5issillyMar 15, 1986A
-53-5388.5helloaeccentricFeb 27, 2086O
195195-858orangefruitgarbageMar 15, 1986I
181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /examples/multicolumn-sort.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Stupid jQuery table sort 5 | 6 | 7 | 12 | 30 | 31 | 32 | 33 | 34 | 35 |

Multicolumn sort

36 | 37 |

This example shows how to perform a multicolumn sort. A multicolumn sort 38 | allows you to define what column to sort by in the event of a tie with two 39 | elements in the initial column sorted.

40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 |
intfloatstring
110.0a
110.0a
210.0b
020.0c
130.0b
230.0a
010.0b
020.0a
010.0c
120.0a
210.0b
330.0a
230.0b
117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /examples/with-settings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Stupid jQuery table sort 5 | 6 | 7 | 28 | 46 | 47 | 48 | 49 | 50 | 51 |

StupidTable with settings

52 | 53 |

This page shows how specific behaviors can be introduced by providing 54 | settings to StupidTable. View the source of this page to see the settings in 55 | use.

56 | 57 |
58 | 59 |

Example 1

60 | 61 |

This table does not redraw when attempting to sort a column that has identical values in all rows.

62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 |
intfloatstringint (identical)
15-.18banana99
9536coke99
2-152.5apple99
-5388.5zebra99
195-858orange99
105 | 106 |

107 | var $table = $("#example-1");
108 | $table.stupidtable_settings({
109 |     should_redraw: function(sort_info){
110 |       var sorted_column = sort_info.column;
111 |       var first_val = sorted_column[0];
112 |       var last_val = sorted_column[sorted_column.length - 1][0];
113 | 
114 |       // If first and last element of the sorted column are the same, we
115 |       // can assume all elements are the same.
116 |       return sort_info.compare_fn(first_val, last_val) !== 0;
117 |     }
118 | });
119 | $table.stupidtable();
120 | 
121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stupid-table-plugin", 3 | "version": "1.1.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "acorn": { 8 | "version": "5.7.3", 9 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", 10 | "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", 11 | "dev": true 12 | }, 13 | "acorn-jsx": { 14 | "version": "3.0.1", 15 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", 16 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", 17 | "dev": true, 18 | "requires": { 19 | "acorn": "^3.0.4" 20 | }, 21 | "dependencies": { 22 | "acorn": { 23 | "version": "3.3.0", 24 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 25 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", 26 | "dev": true 27 | } 28 | } 29 | }, 30 | "ajv": { 31 | "version": "5.5.2", 32 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 33 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 34 | "dev": true, 35 | "requires": { 36 | "co": "^4.6.0", 37 | "fast-deep-equal": "^1.0.0", 38 | "fast-json-stable-stringify": "^2.0.0", 39 | "json-schema-traverse": "^0.3.0" 40 | } 41 | }, 42 | "ajv-keywords": { 43 | "version": "2.1.1", 44 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", 45 | "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", 46 | "dev": true 47 | }, 48 | "ansi-escapes": { 49 | "version": "3.2.0", 50 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", 51 | "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", 52 | "dev": true 53 | }, 54 | "ansi-regex": { 55 | "version": "2.1.1", 56 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 57 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 58 | "dev": true 59 | }, 60 | "ansi-styles": { 61 | "version": "2.2.1", 62 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 63 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 64 | "dev": true 65 | }, 66 | "argparse": { 67 | "version": "1.0.10", 68 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 69 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 70 | "dev": true, 71 | "requires": { 72 | "sprintf-js": "~1.0.2" 73 | } 74 | }, 75 | "babel-code-frame": { 76 | "version": "6.26.0", 77 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", 78 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", 79 | "dev": true, 80 | "requires": { 81 | "chalk": "^1.1.3", 82 | "esutils": "^2.0.2", 83 | "js-tokens": "^3.0.2" 84 | }, 85 | "dependencies": { 86 | "chalk": { 87 | "version": "1.1.3", 88 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 89 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 90 | "dev": true, 91 | "requires": { 92 | "ansi-styles": "^2.2.1", 93 | "escape-string-regexp": "^1.0.2", 94 | "has-ansi": "^2.0.0", 95 | "strip-ansi": "^3.0.0", 96 | "supports-color": "^2.0.0" 97 | } 98 | }, 99 | "strip-ansi": { 100 | "version": "3.0.1", 101 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 102 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 103 | "dev": true, 104 | "requires": { 105 | "ansi-regex": "^2.0.0" 106 | } 107 | } 108 | } 109 | }, 110 | "balanced-match": { 111 | "version": "1.0.0", 112 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 113 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 114 | "dev": true 115 | }, 116 | "brace-expansion": { 117 | "version": "1.1.11", 118 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 119 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 120 | "dev": true, 121 | "requires": { 122 | "balanced-match": "^1.0.0", 123 | "concat-map": "0.0.1" 124 | } 125 | }, 126 | "buffer-from": { 127 | "version": "1.1.1", 128 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 129 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 130 | "dev": true 131 | }, 132 | "caller-path": { 133 | "version": "0.1.0", 134 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 135 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 136 | "dev": true, 137 | "requires": { 138 | "callsites": "^0.2.0" 139 | } 140 | }, 141 | "callsites": { 142 | "version": "0.2.0", 143 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 144 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 145 | "dev": true 146 | }, 147 | "camel-case": { 148 | "version": "3.0.0", 149 | "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", 150 | "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", 151 | "dev": true, 152 | "requires": { 153 | "no-case": "^2.2.0", 154 | "upper-case": "^1.1.1" 155 | } 156 | }, 157 | "chalk": { 158 | "version": "2.4.2", 159 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 160 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 161 | "dev": true, 162 | "requires": { 163 | "ansi-styles": "^3.2.1", 164 | "escape-string-regexp": "^1.0.5", 165 | "supports-color": "^5.3.0" 166 | }, 167 | "dependencies": { 168 | "ansi-styles": { 169 | "version": "3.2.1", 170 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 171 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 172 | "dev": true, 173 | "requires": { 174 | "color-convert": "^1.9.0" 175 | } 176 | }, 177 | "supports-color": { 178 | "version": "5.5.0", 179 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 180 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 181 | "dev": true, 182 | "requires": { 183 | "has-flag": "^3.0.0" 184 | } 185 | } 186 | } 187 | }, 188 | "chardet": { 189 | "version": "0.4.2", 190 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", 191 | "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", 192 | "dev": true 193 | }, 194 | "checkup": { 195 | "version": "1.3.0", 196 | "resolved": "https://registry.npmjs.org/checkup/-/checkup-1.3.0.tgz", 197 | "integrity": "sha1-04ACdv6l0PJH/8lRvnjIsC+ODXY=", 198 | "dev": true 199 | }, 200 | "circular-json": { 201 | "version": "0.3.3", 202 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", 203 | "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", 204 | "dev": true 205 | }, 206 | "clean-css": { 207 | "version": "4.1.11", 208 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", 209 | "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", 210 | "dev": true, 211 | "requires": { 212 | "source-map": "0.5.x" 213 | } 214 | }, 215 | "cli-cursor": { 216 | "version": "2.1.0", 217 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 218 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 219 | "dev": true, 220 | "requires": { 221 | "restore-cursor": "^2.0.0" 222 | } 223 | }, 224 | "cli-width": { 225 | "version": "2.2.0", 226 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 227 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", 228 | "dev": true 229 | }, 230 | "co": { 231 | "version": "4.6.0", 232 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 233 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 234 | "dev": true 235 | }, 236 | "color-convert": { 237 | "version": "1.9.3", 238 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 239 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 240 | "dev": true, 241 | "requires": { 242 | "color-name": "1.1.3" 243 | } 244 | }, 245 | "color-name": { 246 | "version": "1.1.3", 247 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 248 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 249 | "dev": true 250 | }, 251 | "commander": { 252 | "version": "2.15.1", 253 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", 254 | "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", 255 | "dev": true 256 | }, 257 | "concat-map": { 258 | "version": "0.0.1", 259 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 260 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 261 | "dev": true 262 | }, 263 | "concat-stream": { 264 | "version": "1.6.2", 265 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 266 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 267 | "dev": true, 268 | "requires": { 269 | "buffer-from": "^1.0.0", 270 | "inherits": "^2.0.3", 271 | "readable-stream": "^2.2.2", 272 | "typedarray": "^0.0.6" 273 | } 274 | }, 275 | "core-util-is": { 276 | "version": "1.0.2", 277 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 278 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 279 | "dev": true 280 | }, 281 | "cross-spawn": { 282 | "version": "5.1.0", 283 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", 284 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", 285 | "dev": true, 286 | "requires": { 287 | "lru-cache": "^4.0.1", 288 | "shebang-command": "^1.2.0", 289 | "which": "^1.2.9" 290 | } 291 | }, 292 | "css-b64-images": { 293 | "version": "0.2.5", 294 | "resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz", 295 | "integrity": "sha1-QgBdgyBLK0pdk7axpWRBM7WSegI=", 296 | "dev": true 297 | }, 298 | "debug": { 299 | "version": "3.1.0", 300 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 301 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 302 | "dev": true, 303 | "requires": { 304 | "ms": "2.0.0" 305 | } 306 | }, 307 | "deep-is": { 308 | "version": "0.1.3", 309 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 310 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 311 | "dev": true 312 | }, 313 | "doctrine": { 314 | "version": "2.1.0", 315 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 316 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 317 | "dev": true, 318 | "requires": { 319 | "esutils": "^2.0.2" 320 | } 321 | }, 322 | "escape-string-regexp": { 323 | "version": "1.0.5", 324 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 325 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 326 | "dev": true 327 | }, 328 | "eslint": { 329 | "version": "4.18.2", 330 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz", 331 | "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==", 332 | "dev": true, 333 | "requires": { 334 | "ajv": "^5.3.0", 335 | "babel-code-frame": "^6.22.0", 336 | "chalk": "^2.1.0", 337 | "concat-stream": "^1.6.0", 338 | "cross-spawn": "^5.1.0", 339 | "debug": "^3.1.0", 340 | "doctrine": "^2.1.0", 341 | "eslint-scope": "^3.7.1", 342 | "eslint-visitor-keys": "^1.0.0", 343 | "espree": "^3.5.2", 344 | "esquery": "^1.0.0", 345 | "esutils": "^2.0.2", 346 | "file-entry-cache": "^2.0.0", 347 | "functional-red-black-tree": "^1.0.1", 348 | "glob": "^7.1.2", 349 | "globals": "^11.0.1", 350 | "ignore": "^3.3.3", 351 | "imurmurhash": "^0.1.4", 352 | "inquirer": "^3.0.6", 353 | "is-resolvable": "^1.0.0", 354 | "js-yaml": "^3.9.1", 355 | "json-stable-stringify-without-jsonify": "^1.0.1", 356 | "levn": "^0.3.0", 357 | "lodash": "^4.17.4", 358 | "minimatch": "^3.0.2", 359 | "mkdirp": "^0.5.1", 360 | "natural-compare": "^1.4.0", 361 | "optionator": "^0.8.2", 362 | "path-is-inside": "^1.0.2", 363 | "pluralize": "^7.0.0", 364 | "progress": "^2.0.0", 365 | "require-uncached": "^1.0.3", 366 | "semver": "^5.3.0", 367 | "strip-ansi": "^4.0.0", 368 | "strip-json-comments": "~2.0.1", 369 | "table": "4.0.2", 370 | "text-table": "~0.2.0" 371 | } 372 | }, 373 | "eslint-scope": { 374 | "version": "3.7.3", 375 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", 376 | "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", 377 | "dev": true, 378 | "requires": { 379 | "esrecurse": "^4.1.0", 380 | "estraverse": "^4.1.1" 381 | } 382 | }, 383 | "eslint-visitor-keys": { 384 | "version": "1.1.0", 385 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", 386 | "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", 387 | "dev": true 388 | }, 389 | "espree": { 390 | "version": "3.5.4", 391 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", 392 | "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", 393 | "dev": true, 394 | "requires": { 395 | "acorn": "^5.5.0", 396 | "acorn-jsx": "^3.0.0" 397 | } 398 | }, 399 | "esprima": { 400 | "version": "4.0.1", 401 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 402 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 403 | "dev": true 404 | }, 405 | "esquery": { 406 | "version": "1.0.1", 407 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", 408 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", 409 | "dev": true, 410 | "requires": { 411 | "estraverse": "^4.0.0" 412 | } 413 | }, 414 | "esrecurse": { 415 | "version": "4.2.1", 416 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 417 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 418 | "dev": true, 419 | "requires": { 420 | "estraverse": "^4.1.0" 421 | } 422 | }, 423 | "estraverse": { 424 | "version": "4.3.0", 425 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 426 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 427 | "dev": true 428 | }, 429 | "esutils": { 430 | "version": "2.0.3", 431 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 432 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 433 | "dev": true 434 | }, 435 | "execon": { 436 | "version": "1.2.9", 437 | "resolved": "https://registry.npmjs.org/execon/-/execon-1.2.9.tgz", 438 | "integrity": "sha1-bbETM9zIJPHxPnMX/tDZSi8mSR8=", 439 | "dev": true 440 | }, 441 | "external-editor": { 442 | "version": "2.2.0", 443 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", 444 | "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", 445 | "dev": true, 446 | "requires": { 447 | "chardet": "^0.4.0", 448 | "iconv-lite": "^0.4.17", 449 | "tmp": "^0.0.33" 450 | } 451 | }, 452 | "fast-deep-equal": { 453 | "version": "1.1.0", 454 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", 455 | "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", 456 | "dev": true 457 | }, 458 | "fast-json-stable-stringify": { 459 | "version": "2.0.0", 460 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 461 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 462 | "dev": true 463 | }, 464 | "fast-levenshtein": { 465 | "version": "2.0.6", 466 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 467 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 468 | "dev": true 469 | }, 470 | "figures": { 471 | "version": "2.0.0", 472 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 473 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 474 | "dev": true, 475 | "requires": { 476 | "escape-string-regexp": "^1.0.5" 477 | } 478 | }, 479 | "file-entry-cache": { 480 | "version": "2.0.0", 481 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 482 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 483 | "dev": true, 484 | "requires": { 485 | "flat-cache": "^1.2.1", 486 | "object-assign": "^4.0.1" 487 | } 488 | }, 489 | "flat-cache": { 490 | "version": "1.3.4", 491 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", 492 | "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", 493 | "dev": true, 494 | "requires": { 495 | "circular-json": "^0.3.1", 496 | "graceful-fs": "^4.1.2", 497 | "rimraf": "~2.6.2", 498 | "write": "^0.2.1" 499 | } 500 | }, 501 | "fs.realpath": { 502 | "version": "1.0.0", 503 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 504 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 505 | "dev": true 506 | }, 507 | "functional-red-black-tree": { 508 | "version": "1.0.1", 509 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 510 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 511 | "dev": true 512 | }, 513 | "glob": { 514 | "version": "7.1.6", 515 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 516 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 517 | "dev": true, 518 | "requires": { 519 | "fs.realpath": "^1.0.0", 520 | "inflight": "^1.0.4", 521 | "inherits": "2", 522 | "minimatch": "^3.0.4", 523 | "once": "^1.3.0", 524 | "path-is-absolute": "^1.0.0" 525 | } 526 | }, 527 | "globals": { 528 | "version": "11.12.0", 529 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 530 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 531 | "dev": true 532 | }, 533 | "graceful-fs": { 534 | "version": "4.2.3", 535 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", 536 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", 537 | "dev": true 538 | }, 539 | "has-ansi": { 540 | "version": "2.0.0", 541 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 542 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 543 | "dev": true, 544 | "requires": { 545 | "ansi-regex": "^2.0.0" 546 | } 547 | }, 548 | "has-flag": { 549 | "version": "3.0.0", 550 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 551 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 552 | "dev": true 553 | }, 554 | "he": { 555 | "version": "1.1.1", 556 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", 557 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", 558 | "dev": true 559 | }, 560 | "html-minifier": { 561 | "version": "3.5.13", 562 | "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.13.tgz", 563 | "integrity": "sha512-B7P99uf0LPQ5lslyhrAZAXE7Lk1tpiv52KVapKbeFhgqNMUI7JBd/fYLX55imu3Rz7sCTzZM6r/IBe4oT7qCjg==", 564 | "dev": true, 565 | "requires": { 566 | "camel-case": "3.0.x", 567 | "clean-css": "4.1.x", 568 | "commander": "2.15.x", 569 | "he": "1.1.x", 570 | "param-case": "2.1.x", 571 | "relateurl": "0.2.x", 572 | "uglify-js": "3.3.x" 573 | } 574 | }, 575 | "iconv-lite": { 576 | "version": "0.4.24", 577 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 578 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 579 | "dev": true, 580 | "requires": { 581 | "safer-buffer": ">= 2.1.2 < 3" 582 | } 583 | }, 584 | "ignore": { 585 | "version": "3.3.10", 586 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", 587 | "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", 588 | "dev": true 589 | }, 590 | "imurmurhash": { 591 | "version": "0.1.4", 592 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 593 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 594 | "dev": true 595 | }, 596 | "inflight": { 597 | "version": "1.0.6", 598 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 599 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 600 | "dev": true, 601 | "requires": { 602 | "once": "^1.3.0", 603 | "wrappy": "1" 604 | } 605 | }, 606 | "inherits": { 607 | "version": "2.0.4", 608 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 609 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 610 | "dev": true 611 | }, 612 | "inquirer": { 613 | "version": "3.3.0", 614 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", 615 | "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", 616 | "dev": true, 617 | "requires": { 618 | "ansi-escapes": "^3.0.0", 619 | "chalk": "^2.0.0", 620 | "cli-cursor": "^2.1.0", 621 | "cli-width": "^2.0.0", 622 | "external-editor": "^2.0.4", 623 | "figures": "^2.0.0", 624 | "lodash": "^4.3.0", 625 | "mute-stream": "0.0.7", 626 | "run-async": "^2.2.0", 627 | "rx-lite": "^4.0.8", 628 | "rx-lite-aggregates": "^4.0.8", 629 | "string-width": "^2.1.0", 630 | "strip-ansi": "^4.0.0", 631 | "through": "^2.3.6" 632 | } 633 | }, 634 | "is-fullwidth-code-point": { 635 | "version": "2.0.0", 636 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 637 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 638 | "dev": true 639 | }, 640 | "is-promise": { 641 | "version": "2.1.0", 642 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 643 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 644 | "dev": true 645 | }, 646 | "is-resolvable": { 647 | "version": "1.1.0", 648 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", 649 | "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", 650 | "dev": true 651 | }, 652 | "isarray": { 653 | "version": "1.0.0", 654 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 655 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 656 | "dev": true 657 | }, 658 | "ischanged": { 659 | "version": "1.0.18", 660 | "resolved": "https://registry.npmjs.org/ischanged/-/ischanged-1.0.18.tgz", 661 | "integrity": "sha1-IFZ/pssBgcVrme2zz8GMrbGWYcQ=", 662 | "dev": true, 663 | "requires": { 664 | "checkup": "~1.3.0", 665 | "debug": "^2.3.0", 666 | "mkdirp": "~0.5.0", 667 | "readjson": "~1.1.0", 668 | "timem": "~1.1.0", 669 | "writejson": "~1.1.0" 670 | }, 671 | "dependencies": { 672 | "debug": { 673 | "version": "2.6.9", 674 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 675 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 676 | "dev": true, 677 | "requires": { 678 | "ms": "2.0.0" 679 | } 680 | } 681 | } 682 | }, 683 | "isexe": { 684 | "version": "2.0.0", 685 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 686 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 687 | "dev": true 688 | }, 689 | "js-tokens": { 690 | "version": "3.0.2", 691 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 692 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 693 | "dev": true 694 | }, 695 | "js-yaml": { 696 | "version": "3.13.1", 697 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 698 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 699 | "dev": true, 700 | "requires": { 701 | "argparse": "^1.0.7", 702 | "esprima": "^4.0.0" 703 | } 704 | }, 705 | "json-schema-traverse": { 706 | "version": "0.3.1", 707 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 708 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", 709 | "dev": true 710 | }, 711 | "json-stable-stringify-without-jsonify": { 712 | "version": "1.0.1", 713 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 714 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 715 | "dev": true 716 | }, 717 | "levn": { 718 | "version": "0.3.0", 719 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 720 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 721 | "dev": true, 722 | "requires": { 723 | "prelude-ls": "~1.1.2", 724 | "type-check": "~0.3.2" 725 | } 726 | }, 727 | "lodash": { 728 | "version": "4.17.15", 729 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 730 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 731 | "dev": true 732 | }, 733 | "lower-case": { 734 | "version": "1.1.4", 735 | "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", 736 | "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", 737 | "dev": true 738 | }, 739 | "lru-cache": { 740 | "version": "4.1.5", 741 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 742 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 743 | "dev": true, 744 | "requires": { 745 | "pseudomap": "^1.0.2", 746 | "yallist": "^2.1.2" 747 | } 748 | }, 749 | "mimic-fn": { 750 | "version": "1.2.0", 751 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 752 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", 753 | "dev": true 754 | }, 755 | "minify": { 756 | "version": "3.0.5", 757 | "resolved": "https://registry.npmjs.org/minify/-/minify-3.0.5.tgz", 758 | "integrity": "sha512-siVF3AQ4G1ihgQ15su9aiZ+2XIgs0SKPq4f8apvhdKl+hms8Z+D7uzJ5a50xC7de18Xoqqw7hGn2kfMJP5qcpA==", 759 | "dev": true, 760 | "requires": { 761 | "clean-css": "^4.1.6", 762 | "css-b64-images": "~0.2.5", 763 | "debug": "^3.0.0", 764 | "execon": "^1.2.9", 765 | "html-minifier": "^3.0.1", 766 | "tomas": "^2.0.0", 767 | "try-catch": "^2.0.0", 768 | "uglify-js": "^3.0.3" 769 | } 770 | }, 771 | "minimatch": { 772 | "version": "3.0.4", 773 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 774 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 775 | "dev": true, 776 | "requires": { 777 | "brace-expansion": "^1.1.7" 778 | } 779 | }, 780 | "minimist": { 781 | "version": "0.0.8", 782 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 783 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 784 | "dev": true 785 | }, 786 | "mkdirp": { 787 | "version": "0.5.1", 788 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 789 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 790 | "dev": true, 791 | "requires": { 792 | "minimist": "0.0.8" 793 | } 794 | }, 795 | "ms": { 796 | "version": "2.0.0", 797 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 798 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 799 | "dev": true 800 | }, 801 | "mute-stream": { 802 | "version": "0.0.7", 803 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 804 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 805 | "dev": true 806 | }, 807 | "natural-compare": { 808 | "version": "1.4.0", 809 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 810 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 811 | "dev": true 812 | }, 813 | "no-case": { 814 | "version": "2.3.2", 815 | "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", 816 | "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", 817 | "dev": true, 818 | "requires": { 819 | "lower-case": "^1.1.1" 820 | } 821 | }, 822 | "object-assign": { 823 | "version": "4.1.1", 824 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 825 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 826 | "dev": true 827 | }, 828 | "once": { 829 | "version": "1.4.0", 830 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 831 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 832 | "dev": true, 833 | "requires": { 834 | "wrappy": "1" 835 | } 836 | }, 837 | "onetime": { 838 | "version": "2.0.1", 839 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 840 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 841 | "dev": true, 842 | "requires": { 843 | "mimic-fn": "^1.0.0" 844 | } 845 | }, 846 | "optionator": { 847 | "version": "0.8.3", 848 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", 849 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", 850 | "dev": true, 851 | "requires": { 852 | "deep-is": "~0.1.3", 853 | "fast-levenshtein": "~2.0.6", 854 | "levn": "~0.3.0", 855 | "prelude-ls": "~1.1.2", 856 | "type-check": "~0.3.2", 857 | "word-wrap": "~1.2.3" 858 | } 859 | }, 860 | "os-tmpdir": { 861 | "version": "1.0.2", 862 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 863 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 864 | "dev": true 865 | }, 866 | "param-case": { 867 | "version": "2.1.1", 868 | "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", 869 | "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", 870 | "dev": true, 871 | "requires": { 872 | "no-case": "^2.2.0" 873 | } 874 | }, 875 | "path-is-absolute": { 876 | "version": "1.0.1", 877 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 878 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 879 | "dev": true 880 | }, 881 | "path-is-inside": { 882 | "version": "1.0.2", 883 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 884 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 885 | "dev": true 886 | }, 887 | "pluralize": { 888 | "version": "7.0.0", 889 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", 890 | "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", 891 | "dev": true 892 | }, 893 | "prelude-ls": { 894 | "version": "1.1.2", 895 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 896 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 897 | "dev": true 898 | }, 899 | "process-nextick-args": { 900 | "version": "2.0.1", 901 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 902 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 903 | "dev": true 904 | }, 905 | "progress": { 906 | "version": "2.0.3", 907 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 908 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 909 | "dev": true 910 | }, 911 | "pseudomap": { 912 | "version": "1.0.2", 913 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 914 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", 915 | "dev": true 916 | }, 917 | "readable-stream": { 918 | "version": "2.3.6", 919 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 920 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 921 | "dev": true, 922 | "requires": { 923 | "core-util-is": "~1.0.0", 924 | "inherits": "~2.0.3", 925 | "isarray": "~1.0.0", 926 | "process-nextick-args": "~2.0.0", 927 | "safe-buffer": "~5.1.1", 928 | "string_decoder": "~1.1.1", 929 | "util-deprecate": "~1.0.1" 930 | } 931 | }, 932 | "readjson": { 933 | "version": "1.1.4", 934 | "resolved": "https://registry.npmjs.org/readjson/-/readjson-1.1.4.tgz", 935 | "integrity": "sha512-H4dRk2S67w3HtE1apnw5wlHpN9qkJ0pen0AcEvyAfnrPfskZIyUOYLXpfN6olDQZI+eUlxg0Yo4lJ2bymujOUA==", 936 | "dev": true, 937 | "requires": { 938 | "try-catch": "^2.0.0" 939 | } 940 | }, 941 | "relateurl": { 942 | "version": "0.2.7", 943 | "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", 944 | "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", 945 | "dev": true 946 | }, 947 | "require-uncached": { 948 | "version": "1.0.3", 949 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", 950 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", 951 | "dev": true, 952 | "requires": { 953 | "caller-path": "^0.1.0", 954 | "resolve-from": "^1.0.0" 955 | } 956 | }, 957 | "resolve-from": { 958 | "version": "1.0.1", 959 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 960 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 961 | "dev": true 962 | }, 963 | "restore-cursor": { 964 | "version": "2.0.0", 965 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 966 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 967 | "dev": true, 968 | "requires": { 969 | "onetime": "^2.0.0", 970 | "signal-exit": "^3.0.2" 971 | } 972 | }, 973 | "rimraf": { 974 | "version": "2.6.3", 975 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 976 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 977 | "dev": true, 978 | "requires": { 979 | "glob": "^7.1.3" 980 | } 981 | }, 982 | "run-async": { 983 | "version": "2.3.0", 984 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 985 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 986 | "dev": true, 987 | "requires": { 988 | "is-promise": "^2.1.0" 989 | } 990 | }, 991 | "rx-lite": { 992 | "version": "4.0.8", 993 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", 994 | "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", 995 | "dev": true 996 | }, 997 | "rx-lite-aggregates": { 998 | "version": "4.0.8", 999 | "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", 1000 | "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", 1001 | "dev": true, 1002 | "requires": { 1003 | "rx-lite": "*" 1004 | } 1005 | }, 1006 | "safe-buffer": { 1007 | "version": "5.1.2", 1008 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1009 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1010 | "dev": true 1011 | }, 1012 | "safer-buffer": { 1013 | "version": "2.1.2", 1014 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1015 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1016 | "dev": true 1017 | }, 1018 | "semver": { 1019 | "version": "5.7.1", 1020 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1021 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1022 | "dev": true 1023 | }, 1024 | "shebang-command": { 1025 | "version": "1.2.0", 1026 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1027 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1028 | "dev": true, 1029 | "requires": { 1030 | "shebang-regex": "^1.0.0" 1031 | } 1032 | }, 1033 | "shebang-regex": { 1034 | "version": "1.0.0", 1035 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1036 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1037 | "dev": true 1038 | }, 1039 | "signal-exit": { 1040 | "version": "3.0.2", 1041 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1042 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1043 | "dev": true 1044 | }, 1045 | "slice-ansi": { 1046 | "version": "1.0.0", 1047 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", 1048 | "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", 1049 | "dev": true, 1050 | "requires": { 1051 | "is-fullwidth-code-point": "^2.0.0" 1052 | } 1053 | }, 1054 | "source-map": { 1055 | "version": "0.5.7", 1056 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1057 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1058 | "dev": true 1059 | }, 1060 | "sprintf-js": { 1061 | "version": "1.0.3", 1062 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1063 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1064 | "dev": true 1065 | }, 1066 | "string-width": { 1067 | "version": "2.1.1", 1068 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1069 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1070 | "dev": true, 1071 | "requires": { 1072 | "is-fullwidth-code-point": "^2.0.0", 1073 | "strip-ansi": "^4.0.0" 1074 | } 1075 | }, 1076 | "string_decoder": { 1077 | "version": "1.1.1", 1078 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1079 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1080 | "dev": true, 1081 | "requires": { 1082 | "safe-buffer": "~5.1.0" 1083 | } 1084 | }, 1085 | "strip-ansi": { 1086 | "version": "4.0.0", 1087 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1088 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1089 | "dev": true, 1090 | "requires": { 1091 | "ansi-regex": "^3.0.0" 1092 | }, 1093 | "dependencies": { 1094 | "ansi-regex": { 1095 | "version": "3.0.0", 1096 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 1097 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 1098 | "dev": true 1099 | } 1100 | } 1101 | }, 1102 | "strip-json-comments": { 1103 | "version": "2.0.1", 1104 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1105 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1106 | "dev": true 1107 | }, 1108 | "supports-color": { 1109 | "version": "2.0.0", 1110 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1111 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 1112 | "dev": true 1113 | }, 1114 | "table": { 1115 | "version": "4.0.2", 1116 | "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", 1117 | "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", 1118 | "dev": true, 1119 | "requires": { 1120 | "ajv": "^5.2.3", 1121 | "ajv-keywords": "^2.1.0", 1122 | "chalk": "^2.1.0", 1123 | "lodash": "^4.17.4", 1124 | "slice-ansi": "1.0.0", 1125 | "string-width": "^2.1.1" 1126 | } 1127 | }, 1128 | "text-table": { 1129 | "version": "0.2.0", 1130 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1131 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1132 | "dev": true 1133 | }, 1134 | "through": { 1135 | "version": "2.3.8", 1136 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1137 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1138 | "dev": true 1139 | }, 1140 | "timem": { 1141 | "version": "1.1.2", 1142 | "resolved": "https://registry.npmjs.org/timem/-/timem-1.1.2.tgz", 1143 | "integrity": "sha1-/pMAbCglOo2lxJKZMGmR+kzE9Aw=", 1144 | "dev": true 1145 | }, 1146 | "tmp": { 1147 | "version": "0.0.33", 1148 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1149 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1150 | "dev": true, 1151 | "requires": { 1152 | "os-tmpdir": "~1.0.2" 1153 | } 1154 | }, 1155 | "tomas": { 1156 | "version": "2.0.2", 1157 | "resolved": "https://registry.npmjs.org/tomas/-/tomas-2.0.2.tgz", 1158 | "integrity": "sha512-IqPlPO4ldadauio6iBEHhgOGWzrddtj4PxvVQT9xnjk8w1AQWzCMeWRYcl1oO7DDOecm3pGxjCRQEQfJwiIAgA==", 1159 | "dev": true, 1160 | "requires": { 1161 | "checkup": "~1.3.0", 1162 | "execon": "~1.2.0", 1163 | "ischanged": "~1.0.7", 1164 | "mkdirp": "~0.5.0" 1165 | } 1166 | }, 1167 | "try-catch": { 1168 | "version": "2.0.0", 1169 | "resolved": "https://registry.npmjs.org/try-catch/-/try-catch-2.0.0.tgz", 1170 | "integrity": "sha512-RPXpVjsbtWgymwGq5F/OWDFsjEzdvzwHFaMjWWW6f/p6+uk/N7YSKJHQfIfGqITfj8qH4cBqCLMnhKZBaKk7Kg==", 1171 | "dev": true 1172 | }, 1173 | "type-check": { 1174 | "version": "0.3.2", 1175 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1176 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1177 | "dev": true, 1178 | "requires": { 1179 | "prelude-ls": "~1.1.2" 1180 | } 1181 | }, 1182 | "typedarray": { 1183 | "version": "0.0.6", 1184 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1185 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 1186 | "dev": true 1187 | }, 1188 | "uglify-js": { 1189 | "version": "3.3.18", 1190 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.18.tgz", 1191 | "integrity": "sha512-VhjIFv93KnTx/ntNi9yTBbfrsWnQnqUy02MT32uqU/5i2oEJ8GAEJ0AwYV206JeOmIzSjm41Ba0iXVKv6j7y9g==", 1192 | "dev": true, 1193 | "requires": { 1194 | "commander": "~2.15.0", 1195 | "source-map": "~0.6.1" 1196 | }, 1197 | "dependencies": { 1198 | "source-map": { 1199 | "version": "0.6.1", 1200 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1201 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1202 | "dev": true 1203 | } 1204 | } 1205 | }, 1206 | "upper-case": { 1207 | "version": "1.1.3", 1208 | "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", 1209 | "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", 1210 | "dev": true 1211 | }, 1212 | "util-deprecate": { 1213 | "version": "1.0.2", 1214 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1215 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1216 | "dev": true 1217 | }, 1218 | "which": { 1219 | "version": "1.3.1", 1220 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1221 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1222 | "dev": true, 1223 | "requires": { 1224 | "isexe": "^2.0.0" 1225 | } 1226 | }, 1227 | "word-wrap": { 1228 | "version": "1.2.3", 1229 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1230 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1231 | "dev": true 1232 | }, 1233 | "wrappy": { 1234 | "version": "1.0.2", 1235 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1236 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1237 | "dev": true 1238 | }, 1239 | "write": { 1240 | "version": "0.2.1", 1241 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 1242 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 1243 | "dev": true, 1244 | "requires": { 1245 | "mkdirp": "^0.5.1" 1246 | } 1247 | }, 1248 | "writejson": { 1249 | "version": "1.1.2", 1250 | "resolved": "https://registry.npmjs.org/writejson/-/writejson-1.1.2.tgz", 1251 | "integrity": "sha512-5iMR/5y0z7VUNI3S+wRWiu02VnbwuPzrwnUbopJA2sz1kWvSm6Phz/1ahbgQ76SO1HGB9d/RI+44rEcBFtZbMw==", 1252 | "dev": true, 1253 | "requires": { 1254 | "try-catch": "^2.0.0" 1255 | } 1256 | }, 1257 | "yallist": { 1258 | "version": "2.1.2", 1259 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 1260 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", 1261 | "dev": true 1262 | } 1263 | } 1264 | } 1265 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stupid-table-plugin", 3 | "version": "1.1.3", 4 | "description": "Stupidly simple jquery table sorting plugin", 5 | "main": "stupidtable.js", 6 | "scripts": { 7 | "lint": "eslint stupidtable.js", 8 | "build": "minify stupidtable.js > stupidtable.min.js" 9 | }, 10 | "directories": { 11 | "example": "examples", 12 | "test": "tests" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/joequery/Stupid-Table-Plugin.git" 17 | }, 18 | "devDependencies": { 19 | "eslint": "4.18.2", 20 | "minify": "^3.0.5" 21 | }, 22 | "peerDependencies": { 23 | "jquery": ">= 1.7.0" 24 | }, 25 | "keywords": [ 26 | "table", 27 | "sort", 28 | "jquery" 29 | ], 30 | "author": "JoeQuery", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/joequery/Stupid-Table-Plugin/issues" 34 | }, 35 | "homepage": "https://github.com/joequery/Stupid-Table-Plugin#readme", 36 | "dependencies": {} 37 | } 38 | -------------------------------------------------------------------------------- /stupidtable.js: -------------------------------------------------------------------------------- 1 | // Stupid jQuery table plugin. 2 | 3 | (function($) { 4 | $.fn.stupidtable = function(sortFns) { 5 | return this.each(function() { 6 | var $table = $(this); 7 | sortFns = sortFns || {}; 8 | sortFns = $.extend({}, $.fn.stupidtable.default_sort_fns, sortFns); 9 | $table.data('sortFns', sortFns); 10 | $table.stupidtable_build(); 11 | 12 | $table.on("click.stupidtable", "thead th", function() { 13 | $(this).stupidsort(); 14 | }); 15 | 16 | // Sort th immediately if data-sort-onload="yes" is specified. Limit to 17 | // the first one found - only one default sort column makes sense anyway. 18 | var $th_onload_sort = $table.find("th[data-sort-onload=yes]").eq(0); 19 | $th_onload_sort.stupidsort(); 20 | }); 21 | }; 22 | 23 | // ------------------------------------------------------------------ 24 | // Default settings 25 | // ------------------------------------------------------------------ 26 | $.fn.stupidtable.default_settings = { 27 | should_redraw: function(sort_info){ 28 | return true; 29 | }, 30 | will_manually_build_table: false 31 | }; 32 | $.fn.stupidtable.dir = {ASC: "asc", DESC: "desc"}; 33 | $.fn.stupidtable.default_sort_fns = { 34 | "int": function(a, b) { 35 | return parseInt(a, 10) - parseInt(b, 10); 36 | }, 37 | "float": function(a, b) { 38 | return parseFloat(a) - parseFloat(b); 39 | }, 40 | "string": function(a, b) { 41 | return a.toString().localeCompare(b.toString()); 42 | }, 43 | "string-ins": function(a, b) { 44 | a = a.toString().toLocaleLowerCase(); 45 | b = b.toString().toLocaleLowerCase(); 46 | return a.localeCompare(b); 47 | } 48 | }; 49 | 50 | // Allow specification of settings on a per-table basis. Call on a table 51 | // jquery object. Call *before* calling .stuidtable(); 52 | $.fn.stupidtable_settings = function(settings) { 53 | return this.each(function() { 54 | var $table = $(this); 55 | var final_settings = $.extend({}, $.fn.stupidtable.default_settings, settings); 56 | $table.stupidtable.settings = final_settings; 57 | }); 58 | }; 59 | 60 | 61 | // Expects $("#mytable").stupidtable() to have already been called. 62 | // Call on a table header. 63 | $.fn.stupidsort = function(force_direction){ 64 | var $this_th = $(this); 65 | var datatype = $this_th.data("sort") || null; 66 | 67 | // No datatype? Nothing to do. 68 | if (datatype === null) { 69 | return; 70 | } 71 | 72 | var $table = $this_th.closest("table"); 73 | 74 | var sort_info = { 75 | $th: $this_th, 76 | $table: $table, 77 | datatype: datatype 78 | }; 79 | 80 | 81 | // Bring in default settings if none provided 82 | if(!$table.stupidtable.settings){ 83 | $table.stupidtable.settings = $.extend({}, $.fn.stupidtable.default_settings); 84 | } 85 | 86 | sort_info.compare_fn = $table.data('sortFns')[datatype]; 87 | sort_info.th_index = calculateTHIndex(sort_info); 88 | sort_info.sort_dir = calculateSortDir(force_direction, sort_info); 89 | 90 | $this_th.data("sort-dir", sort_info.sort_dir); 91 | $table.trigger("beforetablesort", {column: sort_info.th_index, direction: sort_info.sort_dir, $th: $this_th}); 92 | 93 | // More reliable method of forcing a redraw 94 | $table.css("display"); 95 | 96 | // Run sorting asynchronously on a timout to force browser redraw after 97 | // `beforetablesort` callback. Also avoids locking up the browser too much. 98 | setTimeout(function() { 99 | if(!$table.stupidtable.settings.will_manually_build_table){ 100 | $table.stupidtable_build(); 101 | } 102 | var table_structure = sortTable(sort_info); 103 | var trs = getTableRowsFromTableStructure(table_structure, sort_info); 104 | 105 | if(!$table.stupidtable.settings.should_redraw(sort_info)){ 106 | return; 107 | } 108 | $table.children("tbody").append(trs); 109 | 110 | updateElementData(sort_info); 111 | $table.trigger("aftertablesort", {column: sort_info.th_index, direction: sort_info.sort_dir, $th: $this_th}); 112 | $table.css("display"); 113 | 114 | }, 10); 115 | return $this_th; 116 | }; 117 | 118 | // Call on a sortable td to update its value in the sort. This should be the 119 | // only mechanism used to update a cell's sort value. If your display value is 120 | // different from your sort value, use jQuery's .text() or .html() to update 121 | // the td contents, Assumes stupidtable has already been called for the table. 122 | $.fn.updateSortVal = function(new_sort_val){ 123 | var $this_td = $(this); 124 | if($this_td.is('[data-sort-value]')){ 125 | // For visual consistency with the .data cache 126 | $this_td.attr('data-sort-value', new_sort_val); 127 | } 128 | $this_td.data("sort-value", new_sort_val); 129 | return $this_td; 130 | }; 131 | 132 | 133 | $.fn.stupidtable_build = function(){ 134 | return this.each(function() { 135 | var $table = $(this); 136 | var table_structure = []; 137 | var trs = $table.children("tbody").children("tr"); 138 | trs.each(function(index,tr) { 139 | 140 | // ==================================================================== 141 | // Transfer to using internal table structure 142 | // ==================================================================== 143 | var ele = { 144 | $tr: $(tr), 145 | columns: [], 146 | index: index 147 | }; 148 | 149 | $(tr).children('td').each(function(idx, td){ 150 | var sort_val = $(td).data("sort-value"); 151 | 152 | // Store and read from the .data cache for display text only sorts 153 | // instead of looking through the DOM every time 154 | if(typeof(sort_val) === "undefined"){ 155 | var txt = $(td).text(); 156 | $(td).data('sort-value', txt); 157 | sort_val = txt; 158 | } 159 | ele.columns.push(sort_val); 160 | }); 161 | table_structure.push(ele); 162 | }); 163 | $table.data('stupidsort_internaltable', table_structure); 164 | }); 165 | }; 166 | 167 | // ==================================================================== 168 | // Private functions 169 | // ==================================================================== 170 | var sortTable = function(sort_info){ 171 | var table_structure = sort_info.$table.data('stupidsort_internaltable'); 172 | var th_index = sort_info.th_index; 173 | var $th = sort_info.$th; 174 | 175 | var multicolumn_target_str = $th.data('sort-multicolumn'); 176 | var multicolumn_targets; 177 | if(multicolumn_target_str){ 178 | multicolumn_targets = multicolumn_target_str.split(','); 179 | } 180 | else{ 181 | multicolumn_targets = []; 182 | } 183 | var multicolumn_th_targets = $.map(multicolumn_targets, function(identifier, i){ 184 | return get_th(sort_info.$table, identifier); 185 | }); 186 | 187 | table_structure.sort(function(e1, e2){ 188 | var multicolumns = multicolumn_th_targets.slice(0); // shallow copy 189 | var diff = sort_info.compare_fn(e1.columns[th_index], e2.columns[th_index]); 190 | while(diff === 0 && multicolumns.length){ 191 | var multicolumn = multicolumns[0]; 192 | var datatype = multicolumn.$e.data("sort"); 193 | var multiCloumnSortMethod = sort_info.$table.data('sortFns')[datatype]; 194 | diff = multiCloumnSortMethod(e1.columns[multicolumn.index], e2.columns[multicolumn.index]); 195 | multicolumns.shift(); 196 | } 197 | // Sort by position in the table if values are the same. This enforces a 198 | // stable sort across all browsers. See https://bugs.chromium.org/p/v8/issues/detail?id=90 199 | if (diff === 0) 200 | return e1.index - e2.index; 201 | else 202 | return diff; 203 | 204 | }); 205 | 206 | if (sort_info.sort_dir != $.fn.stupidtable.dir.ASC){ 207 | table_structure.reverse(); 208 | } 209 | return table_structure; 210 | }; 211 | 212 | var get_th = function($table, identifier){ 213 | // identifier can be a th id or a th index number; 214 | var $table_ths = $table.find('th'); 215 | var index = parseInt(identifier, 10); 216 | var $th; 217 | if(!index && index !== 0){ 218 | $th = $table_ths.siblings('#' + identifier); 219 | index = $table_ths.index($th); 220 | } 221 | else{ 222 | $th = $table_ths.eq(index); 223 | } 224 | return {index: index, $e: $th}; 225 | }; 226 | 227 | var getTableRowsFromTableStructure = function(table_structure, sort_info){ 228 | // Gather individual column for callbacks 229 | var column = $.map(table_structure, function(ele, i){ 230 | return [[ele.columns[sort_info.th_index], ele.$tr, i]]; 231 | }); 232 | 233 | /* Side effect */ 234 | sort_info.column = column; 235 | 236 | // Replace the content of tbody with the sorted rows. Strangely 237 | // enough, .append accomplishes this for us. 238 | return $.map(table_structure, function(ele) { return ele.$tr; }); 239 | 240 | }; 241 | 242 | var updateElementData = function(sort_info){ 243 | var $table = sort_info.$table; 244 | var $this_th = sort_info.$th; 245 | var sort_dir = $this_th.data('sort-dir'); 246 | 247 | 248 | // Reset siblings 249 | $table.find("th").data("sort-dir", null).removeClass("sorting-desc sorting-asc"); 250 | $this_th.data("sort-dir", sort_dir).addClass("sorting-"+sort_dir); 251 | }; 252 | 253 | var calculateSortDir = function(force_direction, sort_info){ 254 | var sort_dir; 255 | var $this_th = sort_info.$th; 256 | var dir = $.fn.stupidtable.dir; 257 | 258 | if(force_direction){ 259 | sort_dir = force_direction; 260 | } 261 | else{ 262 | sort_dir = force_direction || $this_th.data("sort-default") || dir.ASC; 263 | if ($this_th.data("sort-dir")) 264 | sort_dir = $this_th.data("sort-dir") === dir.ASC ? dir.DESC : dir.ASC; 265 | } 266 | return sort_dir; 267 | }; 268 | 269 | var calculateTHIndex = function(sort_info){ 270 | var th_index = 0; 271 | var base_index = sort_info.$th.index(); 272 | sort_info.$th.parents("tr").find("th").slice(0, base_index).each(function() { 273 | var cols = $(this).attr("colspan") || 1; 274 | th_index += parseInt(cols,10); 275 | }); 276 | return th_index; 277 | }; 278 | 279 | })(window.jQuery); 280 | -------------------------------------------------------------------------------- /stupidtable.min.js: -------------------------------------------------------------------------------- 1 | !function(i){i.fn.stupidtable=function(n){return this.each(function(){var t=i(this);n=n||{},n=i.extend({},i.fn.stupidtable.default_sort_fns,n),t.data("sortFns",n),t.stupidtable_build(),t.on("click.stupidtable","thead th",function(){i(this).stupidsort()}),t.find("th[data-sort-onload=yes]").eq(0).stupidsort()})},i.fn.stupidtable.default_settings={should_redraw:function(t){return!0},will_manually_build_table:!1},i.fn.stupidtable.dir={ASC:"asc",DESC:"desc"},i.fn.stupidtable.default_sort_fns={int:function(t,n){return parseInt(t,10)-parseInt(n,10)},float:function(t,n){return parseFloat(t)-parseFloat(n)},string:function(t,n){return t.toString().localeCompare(n.toString())},"string-ins":function(t,n){return t=t.toString().toLocaleLowerCase(),n=n.toString().toLocaleLowerCase(),t.localeCompare(n)}},i.fn.stupidtable_settings=function(a){return this.each(function(){var t=i(this),n=i.extend({},i.fn.stupidtable.default_settings,a);t.stupidtable.settings=n})},i.fn.stupidsort=function(t){var a=i(this),n=a.data("sort")||null;if(null!==n){var r=a.closest("table"),e={$th:a,$table:r,datatype:n};return r.stupidtable.settings||(r.stupidtable.settings=i.extend({},i.fn.stupidtable.default_settings)),e.compare_fn=r.data("sortFns")[n],e.th_index=l(e),e.sort_dir=u(t,e),a.data("sort-dir",e.sort_dir),r.trigger("beforetablesort",{column:e.th_index,direction:e.sort_dir,$th:a}),r.css("display"),setTimeout(function(){r.stupidtable.settings.will_manually_build_table||r.stupidtable_build();var t=s(e),n=d(t,e);r.stupidtable.settings.should_redraw(e)&&(r.children("tbody").append(n),o(e),r.trigger("aftertablesort",{column:e.th_index,direction:e.sort_dir,$th:a}),r.css("display"))},10),a}},i.fn.updateSortVal=function(t){var n=i(this);return n.is("[data-sort-value]")&&n.attr("data-sort-value",t),n.data("sort-value",t),n},i.fn.stupidtable_build=function(){return this.each(function(){var t=i(this),a=[];t.children("tbody").children("tr").each(function(t,n){var e={$tr:i(n),columns:[],index:t};i(n).children("td").each(function(t,n){var a=i(n).data("sort-value");if(void 0===a){var r=i(n).text();i(n).data("sort-value",r),a=r}e.columns.push(a)}),a.push(e)}),t.data("stupidsort_internaltable",a)})};var s=function(s){var t,n=s.$table.data("stupidsort_internaltable"),d=s.th_index,a=s.$th.data("sort-multicolumn");t=a?a.split(","):[];var o=i.map(t,function(t,n){return r(s.$table,t)});return n.sort(function(t,n){for(var a=o.slice(0),r=s.compare_fn(t.columns[d],n.columns[d]);0===r&&a.length;){var e=a[0],i=e.$e.data("sort");r=(0,s.$table.data("sortFns")[i])(t.columns[e.index],n.columns[e.index]),a.shift()}return 0===r?t.index-n.index:r}),s.sort_dir!=i.fn.stupidtable.dir.ASC&&n.reverse(),n},r=function(t,n){var a,r=t.find("th"),e=parseInt(n,10);return e||0===e?a=r.eq(e):(a=r.siblings("#"+n),e=r.index(a)),{index:e,$e:a}},d=function(t,a){var n=i.map(t,function(t,n){return[[t.columns[a.th_index],t.$tr,n]]});return a.column=n,i.map(t,function(t){return t.$tr})},o=function(t){var n=t.$table,a=t.$th,r=a.data("sort-dir");n.find("th").data("sort-dir",null).removeClass("sorting-desc sorting-asc"),a.data("sort-dir",r).addClass("sorting-"+r)},u=function(t,n){var a,r=n.$th,e=i.fn.stupidtable.dir;return t?a=t:(a=t||r.data("sort-default")||e.ASC,r.data("sort-dir")&&(a=r.data("sort-dir")===e.ASC?e.DESC:e.ASC)),a},l=function(t){var n=0,a=t.$th.index();return t.$th.parents("tr").find("th").slice(0,a).each(function(){var t=i(this).attr("colspan")||1;n+=parseInt(t,10)}),n}}(window.jQuery); 2 | -------------------------------------------------------------------------------- /tests/qunit.css: -------------------------------------------------------------------------------- 1 | /** 2 | * QUnit v1.12.0 - A JavaScript Unit Testing Framework 3 | * 4 | * http://qunitjs.com 5 | * 6 | * Copyright 2012 jQuery Foundation and other contributors 7 | * Released under the MIT license. 8 | * http://jquery.org/license 9 | */ 10 | 11 | /** Font Family and Sizes */ 12 | 13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 15 | } 16 | 17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 18 | #qunit-tests { font-size: smaller; } 19 | 20 | 21 | /** Resets */ 22 | 23 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 24 | margin: 0; 25 | padding: 0; 26 | } 27 | 28 | 29 | /** Header */ 30 | 31 | #qunit-header { 32 | padding: 0.5em 0 0.5em 1em; 33 | 34 | color: #8699a4; 35 | background-color: #0d3349; 36 | 37 | font-size: 1.5em; 38 | line-height: 1em; 39 | font-weight: normal; 40 | 41 | border-radius: 5px 5px 0 0; 42 | -moz-border-radius: 5px 5px 0 0; 43 | -webkit-border-top-right-radius: 5px; 44 | -webkit-border-top-left-radius: 5px; 45 | } 46 | 47 | #qunit-header a { 48 | text-decoration: none; 49 | color: #c2ccd1; 50 | } 51 | 52 | #qunit-header a:hover, 53 | #qunit-header a:focus { 54 | color: #fff; 55 | } 56 | 57 | #qunit-testrunner-toolbar label { 58 | display: inline-block; 59 | padding: 0 .5em 0 .1em; 60 | } 61 | 62 | #qunit-banner { 63 | height: 5px; 64 | } 65 | 66 | #qunit-testrunner-toolbar { 67 | padding: 0.5em 0 0.5em 2em; 68 | color: #5E740B; 69 | background-color: #eee; 70 | overflow: hidden; 71 | } 72 | 73 | #qunit-userAgent { 74 | padding: 0.5em 0 0.5em 2.5em; 75 | background-color: #2b81af; 76 | color: #fff; 77 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 78 | } 79 | 80 | #qunit-modulefilter-container { 81 | float: right; 82 | } 83 | 84 | /** Tests: Pass/Fail */ 85 | 86 | #qunit-tests { 87 | list-style-position: inside; 88 | } 89 | 90 | #qunit-tests li { 91 | padding: 0.4em 0.5em 0.4em 2.5em; 92 | border-bottom: 1px solid #fff; 93 | list-style-position: inside; 94 | } 95 | 96 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 97 | display: none; 98 | } 99 | 100 | #qunit-tests li strong { 101 | cursor: pointer; 102 | } 103 | 104 | #qunit-tests li a { 105 | padding: 0.5em; 106 | color: #c2ccd1; 107 | text-decoration: none; 108 | } 109 | #qunit-tests li a:hover, 110 | #qunit-tests li a:focus { 111 | color: #000; 112 | } 113 | 114 | #qunit-tests li .runtime { 115 | float: right; 116 | font-size: smaller; 117 | } 118 | 119 | .qunit-assert-list { 120 | margin-top: 0.5em; 121 | padding: 0.5em; 122 | 123 | background-color: #fff; 124 | 125 | border-radius: 5px; 126 | -moz-border-radius: 5px; 127 | -webkit-border-radius: 5px; 128 | } 129 | 130 | .qunit-collapsed { 131 | display: none; 132 | } 133 | 134 | #qunit-tests table { 135 | border-collapse: collapse; 136 | margin-top: .2em; 137 | } 138 | 139 | #qunit-tests th { 140 | text-align: right; 141 | vertical-align: top; 142 | padding: 0 .5em 0 0; 143 | } 144 | 145 | #qunit-tests td { 146 | vertical-align: top; 147 | } 148 | 149 | #qunit-tests pre { 150 | margin: 0; 151 | white-space: pre-wrap; 152 | word-wrap: break-word; 153 | } 154 | 155 | #qunit-tests del { 156 | background-color: #e0f2be; 157 | color: #374e0c; 158 | text-decoration: none; 159 | } 160 | 161 | #qunit-tests ins { 162 | background-color: #ffcaca; 163 | color: #500; 164 | text-decoration: none; 165 | } 166 | 167 | /*** Test Counts */ 168 | 169 | #qunit-tests b.counts { color: black; } 170 | #qunit-tests b.passed { color: #5E740B; } 171 | #qunit-tests b.failed { color: #710909; } 172 | 173 | #qunit-tests li li { 174 | padding: 5px; 175 | background-color: #fff; 176 | border-bottom: none; 177 | list-style-position: inside; 178 | } 179 | 180 | /*** Passing Styles */ 181 | 182 | #qunit-tests li li.pass { 183 | color: #3c510c; 184 | background-color: #fff; 185 | border-left: 10px solid #C6E746; 186 | } 187 | 188 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 189 | #qunit-tests .pass .test-name { color: #366097; } 190 | 191 | #qunit-tests .pass .test-actual, 192 | #qunit-tests .pass .test-expected { color: #999999; } 193 | 194 | #qunit-banner.qunit-pass { background-color: #C6E746; } 195 | 196 | /*** Failing Styles */ 197 | 198 | #qunit-tests li li.fail { 199 | color: #710909; 200 | background-color: #fff; 201 | border-left: 10px solid #EE5757; 202 | white-space: pre; 203 | } 204 | 205 | #qunit-tests > li:last-child { 206 | border-radius: 0 0 5px 5px; 207 | -moz-border-radius: 0 0 5px 5px; 208 | -webkit-border-bottom-right-radius: 5px; 209 | -webkit-border-bottom-left-radius: 5px; 210 | } 211 | 212 | #qunit-tests .fail { color: #000000; background-color: #EE5757; } 213 | #qunit-tests .fail .test-name, 214 | #qunit-tests .fail .module-name { color: #000000; } 215 | 216 | #qunit-tests .fail .test-actual { color: #EE5757; } 217 | #qunit-tests .fail .test-expected { color: green; } 218 | 219 | #qunit-banner.qunit-fail { background-color: #EE5757; } 220 | 221 | 222 | /** Result */ 223 | 224 | #qunit-testresult { 225 | padding: 0.5em 0.5em 0.5em 2.5em; 226 | 227 | color: #2b81af; 228 | background-color: #D2E0E6; 229 | 230 | border-bottom: 1px solid white; 231 | } 232 | #qunit-testresult .module-name { 233 | font-weight: bold; 234 | } 235 | 236 | /** Fixture */ 237 | 238 | 239 | /* Custom styles */ 240 | table { 241 | border-collapse: collapse; 242 | } 243 | th, td { 244 | padding: 5px 10px; 245 | border: 1px solid #999; 246 | } 247 | th { 248 | background-color: #eee; 249 | } 250 | th[data-sort]{ 251 | cursor:pointer; 252 | } 253 | 254 | .test-hidden { 255 | position: absolute; 256 | top: -10000px; 257 | left: -10000px; 258 | width: 1000px; 259 | height: 1000px; 260 | } 261 | -------------------------------------------------------------------------------- /tests/test-min.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Stupid-Table Tests 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 |
22 |
23 | 24 |
25 |

Basic Table

26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
intfloatstring
15-.18banana
9536coke
2-152.5apple
-5388.5zebra
195-858orange
62 |
63 | 64 |
65 |

Basic Onload Table

66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 |
intfloatstring
15-.18banana
9536coke
2-152.5apple
-5388.5zebra
195-858orange
102 |
103 | 104 |
105 |

Complex Table

106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 |
intfloatcaseCan't sort me!dateLetter frequency
15-.18HomerarbitrarySep 15, 2002E
9536purplepointlessAug 07, 2004T
2-152.5issillyMar 15, 1986A
-5388.5aeccentricFeb 27, 2086O
195-858fruitgarbageMar 15, 1986I
160 |
161 | 162 |
163 |

Basic Colspan Table

164 | 165 | 166 | 167 | 169 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 |
Letter 168 | colspan=2Number 170 |
defX91
abcZ82
bcdY70
193 |
194 | 195 |
196 |

Complex Colspan Table

197 | 198 | 199 | 200 | 201 | 202 | 203 | 205 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 |
The Big Table Header
Letter 204 | colspan=2Number 206 |
defX91
abcZ82
bcdY70
229 |
230 | 231 |
232 |

Stability Testing Table

233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 |
(Unsortable) IndexKey
0A
1A
2A
3A
4A
5A
6A
7A
8A
9A
10A
254 |
255 | 256 |
257 |

Multicolumn sort

258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 |
intfloatstring
110.0a
110.0a
210.0b
020.0c
130.0b
230.0a
010.0b
020.0a
010.0c
120.0a
210.0b
330.0a
230.0b
334 |
335 | 336 | 337 | 338 |
339 | 340 | 341 | 342 | -------------------------------------------------------------------------------- /tests/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Stupid-Table Tests 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 |
22 |
23 | 24 |
25 |

Basic Table

26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
intfloatstring
15-.18banana
9536coke
2-152.5apple
-5388.5zebra
195-858orange
62 |
63 | 64 |
65 |

Basic Onload Table

66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 |
intfloatstring
15-.18banana
9536coke
2-152.5apple
-5388.5zebra
195-858orange
102 |
103 | 104 |
105 |

Complex Table

106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 |
intfloatcaseCan't sort me!dateLetter frequency
15-.18HomerarbitrarySep 15, 2002E
9536purplepointlessAug 07, 2004T
2-152.5issillyMar 15, 1986A
-5388.5aeccentricFeb 27, 2086O
195-858fruitgarbageMar 15, 1986I
160 |
161 | 162 |
163 |

Basic Colspan Table

164 | 165 | 166 | 167 | 169 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 |
Letter 168 | colspan=2Number 170 |
defX91
abcZ82
bcdY70
193 |
194 | 195 |
196 |

Complex Colspan Table

197 | 198 | 199 | 200 | 201 | 202 | 203 | 205 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 |
The Big Table Header
Letter 204 | colspan=2Number 206 |
defX91
abcZ82
bcdY70
229 |
230 | 231 |
232 |

Stability Testing Table

233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 |
(Unsortable) IndexKey
0A
1A
2A
3A
4A
5A
6A
7A
8A
9A
10A
254 |
255 | 256 |
257 |

Multicolumn sort

258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 |
intfloatstring
110.0a
110.0a
210.0b
020.0c
130.0b
230.0a
010.0b
020.0a
010.0c
120.0a
210.0b
330.0a
230.0b
334 |
335 | 336 | 337 | 338 |
339 | 340 | 341 | -------------------------------------------------------------------------------- /tests/tests.js: -------------------------------------------------------------------------------- 1 | /* 2 | * IMPORTANT NOTE: Because testing DOM manipulation is really annoying, my 3 | * tests will be created using many setTimeouts. This means if your computer 4 | * is substantially slower than mine, you may get inconsistent results. 5 | */ 6 | $(function(){ 7 | // =========================================================================== 8 | // Test helpers & QUnit callbacks 9 | // =========================================================================== 10 | window.WAIT_TIME_MS = 200; 11 | 12 | var get_column_elements = function($table, col_index){ 13 | var vals = []; 14 | $table.find("tbody tr").each(function(){ 15 | var val = $(this).children("td").eq(col_index).html(); 16 | vals.push(val); 17 | }); 18 | return vals; 19 | }; 20 | 21 | var test_table_state = function(fn){ 22 | setTimeout(function(){ 23 | fn(); 24 | QUnit.start(); 25 | }, WAIT_TIME_MS); 26 | }; 27 | 28 | var date_from_string = function(str){ 29 | var months = ["jan","feb","mar","apr","may","jun","jul", 30 | "aug","sep","oct","nov","dec"]; 31 | var pattern = "^([a-zA-Z]{3})\\s*(\\d{2}),\\s*(\\d{4})$"; 32 | var re = new RegExp(pattern); 33 | var DateParts = re.exec(str).slice(1); 34 | 35 | var Year = DateParts[2]; 36 | var Month = $.inArray(DateParts[0].toLowerCase(), months); 37 | var Day = DateParts[1]; 38 | return new Date(Year, Month, Day); 39 | }; 40 | 41 | /* 42 | * In order to accurately simulate a double click, we have to use a slight pause 43 | * between clicks. During unittests, calling .click() on a column header twice 44 | * without delay causes the sort to get out of order. I have not been able to 45 | * reproduce this manually. Maybe some sort of lock is needed...UNTIL THEN!... 46 | */ 47 | $.fn.doubleclick = function(){ 48 | var $this = $(this); 49 | $this.click(); 50 | setTimeout(function(){ 51 | $this.click(); 52 | }, 10); 53 | return this; 54 | }; 55 | 56 | /* 57 | * Enable stupid tables at the end for manual testing and experiments 58 | */ 59 | QUnit.done(function(){ 60 | $("#complex").stupidtable({ 61 | "date":function(a,b){ 62 | // Get these into date objects for comparison. 63 | var aDate = date_from_string(a); 64 | var bDate = date_from_string(b); 65 | 66 | return aDate - bDate; 67 | } 68 | }); 69 | $("#basic").stupidtable(); 70 | $("#basic-colspan").stupidtable(); 71 | $("#complex-colspan").stupidtable(); 72 | $("#stability-test").stupidtable(); 73 | $("#multicolumn-sort-test").stupidtable(); 74 | $("#qunit-fixture").removeClass("test-hidden"); 75 | }); 76 | 77 | 78 | /* 79 | * Begin tests 80 | * NOTE: when to use test vs asyncTest: When you plan on sorting the table and 81 | * examining the results, you must use the test_table_state function and have 82 | * your test wrapped in asyncTest(). If you wish to only make assertions 83 | * regarding the initial state of the html, just use test(). 84 | */ 85 | 86 | // ============================================================================= 87 | // basic table 88 | // ============================================================================= 89 | test("Basic table initial order", function(){ 90 | var INT_COLUMN = 0; 91 | var FLOAT_COLUMN = 1; 92 | var STRING_COLUMN = 2; 93 | var expected; 94 | var vals; 95 | 96 | var $table = $("#basic"); 97 | 98 | expected = ["15", "95", "2", "-53", "195"]; 99 | vals = get_column_elements($table, INT_COLUMN); 100 | ok(_.isEqual(vals, expected)); 101 | 102 | expected = ["-.18", "36", "-152.5", "88.5", "-858"]; 103 | vals = get_column_elements($table, FLOAT_COLUMN); 104 | ok(_.isEqual(vals, expected)); 105 | 106 | expected = ["banana", "coke", "apple", "zebra", "orange"]; 107 | vals = get_column_elements($table, STRING_COLUMN); 108 | ok(_.isEqual(vals, expected)); 109 | 110 | }); 111 | 112 | asyncTest("Basic int sort", function(){ 113 | var INT_COLUMN = 0; 114 | var $table = $("#basic"); 115 | var $table_cols = $table.find("th"); 116 | 117 | $table.stupidtable(); 118 | $table_cols.eq(INT_COLUMN).click(); 119 | 120 | test_table_state(function(){ 121 | var expected = ["-53", "2", "15", "95", "195"]; 122 | var vals = get_column_elements($table, INT_COLUMN); 123 | ok(_.isEqual(vals, expected)); 124 | }); 125 | }); 126 | 127 | asyncTest("Basic float sort", function(){ 128 | var FLOAT_COLUMN = 1; 129 | var $table = $("#basic"); 130 | var $table_cols = $table.find("th"); 131 | 132 | $table.stupidtable(); 133 | $table_cols.eq(FLOAT_COLUMN).click(); 134 | 135 | test_table_state(function(){ 136 | var expected = ["-858", "-152.5", "-.18", "36", "88.5"]; 137 | var vals = get_column_elements($table, FLOAT_COLUMN); 138 | ok(_.isEqual(vals, expected)); 139 | }); 140 | }); 141 | 142 | asyncTest("Basic string sort", function(){ 143 | var STRING_COLUMN = 2; 144 | var $table = $("#basic"); 145 | var $table_cols = $table.find("th"); 146 | 147 | $table.stupidtable(); 148 | $table_cols.eq(STRING_COLUMN).click(); 149 | 150 | test_table_state(function(){ 151 | var expected = ["apple", "banana", "coke", "orange", "zebra"]; 152 | var vals = get_column_elements($table, STRING_COLUMN); 153 | ok(_.isEqual(vals, expected)); 154 | }); 155 | }); 156 | 157 | asyncTest("Basic alternating sort", function(){ 158 | // A double click should cause the sort to reverse 159 | var INT_COLUMN = 0; 160 | var $table = $("#basic"); 161 | var $table_cols = $table.find("th"); 162 | $table.stupidtable(); 163 | 164 | $table_cols.eq(INT_COLUMN).doubleclick(); 165 | 166 | test_table_state(function(){ 167 | var expected = ["195", "95", "15", "2", "-53"]; 168 | var vals = get_column_elements($table, INT_COLUMN); 169 | ok(_.isEqual(vals, expected)); 170 | }); 171 | }); 172 | 173 | 174 | // ============================================================================= 175 | // complex table 176 | // ============================================================================= 177 | test("Complex table initial order", function(){ 178 | var INT_COLUMN = 0; 179 | var FLOAT_COLUMN = 1; 180 | var STRING_COLUMN = 2; 181 | var NOSORT_COLUMN = 3; 182 | var DATE_COLUMN = 4; 183 | var LETTER_FREQ_COLUMN = 5; 184 | var expected; 185 | var vals; 186 | 187 | var $table = $("#complex"); 188 | 189 | expected = ["15", "95", "2", "-53", "195"]; 190 | vals = get_column_elements($table, INT_COLUMN); 191 | ok(_.isEqual(vals, expected)); 192 | 193 | expected = ["-.18", "36", "-152.5", "88.5", "-858"]; 194 | vals = get_column_elements($table, FLOAT_COLUMN); 195 | ok(_.isEqual(vals, expected)); 196 | 197 | expected = ["Homer", "purple", "is", "a", "fruit"]; 198 | vals = get_column_elements($table, STRING_COLUMN); 199 | ok(_.isEqual(vals, expected)); 200 | 201 | expected = ["arbitrary", "pointless", "silly", "eccentric", "garbage"]; 202 | vals = get_column_elements($table, NOSORT_COLUMN); 203 | ok(_.isEqual(vals, expected)); 204 | 205 | expected = ["Sep 15, 2002", "Aug 07, 2004", "Mar 15, 1986", "Feb 27, 2086", 206 | "Mar 15, 1986"]; 207 | vals = get_column_elements($table, DATE_COLUMN); 208 | ok(_.isEqual(vals, expected)); 209 | 210 | expected = ["E", "T", "A", "O", "I"]; 211 | vals = get_column_elements($table, LETTER_FREQ_COLUMN); 212 | ok(_.isEqual(vals, expected)); 213 | }); 214 | 215 | asyncTest("No data-sort means no sort", function(){ 216 | var NOSORT_COLUMN = 3; 217 | var $table = $("#complex"); 218 | var $table_cols = $table.find("th"); 219 | 220 | $table.stupidtable(); 221 | $table_cols.eq(NOSORT_COLUMN).click(); 222 | 223 | test_table_state(function(){ 224 | var expected = ["arbitrary", "pointless", "silly", "eccentric", "garbage"]; 225 | var vals = get_column_elements($table, NOSORT_COLUMN); 226 | ok(_.isEqual(vals, expected)); 227 | }); 228 | }); 229 | 230 | asyncTest("data-sort-by values should be used over text values", function(){ 231 | var LETTER_FREQ_COLUMN = 5; 232 | var $table = $("#complex"); 233 | var $table_cols = $table.find("th"); 234 | 235 | $table.stupidtable(); 236 | $table_cols.eq(LETTER_FREQ_COLUMN).click(); 237 | 238 | test_table_state(function(){ 239 | var expected = ["E", "T", "A", "O", "I"]; 240 | var vals = get_column_elements($table, LETTER_FREQ_COLUMN); 241 | ok(_.isEqual(vals, expected)); 242 | }); 243 | }); 244 | 245 | asyncTest("case insensitive string sort", function(){ 246 | var STRING_COLUMN = 2; 247 | var $table = $("#complex"); 248 | var $table_cols = $table.find("th"); 249 | 250 | $table.stupidtable(); 251 | $table_cols.eq(STRING_COLUMN).click(); 252 | 253 | test_table_state(function(){ 254 | var expected = ["a", "fruit", "Homer", "is", "purple"]; 255 | var vals = get_column_elements($table, STRING_COLUMN); 256 | ok(_.isEqual(vals, expected)); 257 | }); 258 | }); 259 | 260 | asyncTest("custom sort functions", function(){ 261 | var DATE_COLUMN = 4; 262 | var $table = $("#complex"); 263 | var $table_cols = $table.find("th"); 264 | 265 | 266 | $table.stupidtable({ 267 | "date":function(a,b){ 268 | // Get these into date objects for comparison. 269 | var aDate = date_from_string(a); 270 | var bDate = date_from_string(b); 271 | 272 | return aDate - bDate; 273 | } 274 | }); 275 | 276 | $table_cols.eq(DATE_COLUMN).click(); 277 | test_table_state(function(){ 278 | var expected = ["Mar 15, 1986", "Mar 15, 1986", "Sep 15, 2002", "Aug 07, 2004", 279 | "Feb 27, 2086"]; 280 | var vals = get_column_elements($table, DATE_COLUMN); 281 | ok(_.isEqual(vals, expected)); 282 | }); 283 | 284 | }); 285 | 286 | asyncTest("default sort direction - DESC", function(){ 287 | var FLOAT_COLUMN = 1; 288 | var $table = $("#complex"); 289 | var $table_cols = $table.find("th"); 290 | 291 | $table_cols.eq(FLOAT_COLUMN).data('sort-default', 'desc'); 292 | $table.stupidtable(); 293 | $table_cols.eq(FLOAT_COLUMN).click(); 294 | 295 | test_table_state(function(){ 296 | var expected = ["88.5", "36", "-.18", "-152.5", "-858"]; 297 | var vals = get_column_elements($table, FLOAT_COLUMN); 298 | ok(_.isEqual(vals, expected)); 299 | }); 300 | }); 301 | 302 | asyncTest("default sort direction - ASC", function(){ 303 | var FLOAT_COLUMN = 1; 304 | var $table = $("#complex"); 305 | var $table_cols = $table.find("th"); 306 | 307 | $table_cols.eq(FLOAT_COLUMN).data('sort-default', 'asc'); 308 | $table.stupidtable(); 309 | $table_cols.eq(FLOAT_COLUMN).click(); 310 | 311 | test_table_state(function(){ 312 | var expected = ["-858", "-152.5", "-.18", "36", "88.5"]; 313 | var vals = get_column_elements($table, FLOAT_COLUMN); 314 | ok(_.isEqual(vals, expected)); 315 | }); 316 | }); 317 | 318 | asyncTest("sorting should preserve tbody classes", function(){ 319 | var FLOAT_COLUMN = 1; 320 | var $table = $("#complex"); 321 | var $table_cols = $table.find("th"); 322 | var $tbody = $table.find("tbody"); 323 | var tbodyStyleBefore = $tbody.attr("style"); 324 | 325 | $table.stupidtable(); 326 | 327 | // These are initial values hardcoded in the html. We need to make sure they 328 | // aren't changed once we click a column. 329 | ok($tbody.hasClass('some-tbody-class')); 330 | ok(_.isEqual(tbodyStyleBefore, $tbody.attr("style"))); 331 | 332 | $table_cols.eq(FLOAT_COLUMN).click(); 333 | 334 | test_table_state(function(){ 335 | var $table = $("#complex"); 336 | var $tbody = $table.find("tbody"); 337 | ok($tbody.hasClass('some-tbody-class')); 338 | ok(_.isEqual(tbodyStyleBefore, $tbody.attr("style"))); 339 | }); 340 | }); 341 | 342 | asyncTest("Basic colspan table sort column before colspan column", function(){ 343 | var LETTER_COLUMN = 0; 344 | var $table = $("#basic-colspan"); 345 | var $table_cols = $table.find("th"); 346 | var $tbody = $table.find("tbody"); 347 | 348 | $table.stupidtable(); 349 | $table_cols.eq(LETTER_COLUMN).click(); 350 | 351 | test_table_state(function(){ 352 | var expected = ["abc", "bcd", "def"]; 353 | var vals = get_column_elements($table, LETTER_COLUMN); 354 | ok(_.isEqual(vals, expected)); 355 | }); 356 | }); 357 | 358 | asyncTest("Basic colspan table sort column after colspan column", function(){ 359 | var NUMBER_COLUMN_TH = 2; 360 | var NUMBER_COLUMN = 3; 361 | var $table = $("#basic-colspan"); 362 | var $table_cols = $table.find("th"); 363 | var $tbody = $table.find("tbody"); 364 | 365 | $table.stupidtable(); 366 | $table_cols.eq(NUMBER_COLUMN_TH).click(); 367 | 368 | test_table_state(function(){ 369 | var expected = ["0", "1", "2"]; 370 | var vals = get_column_elements($table, NUMBER_COLUMN); 371 | ok(_.isEqual(vals, expected)); 372 | }); 373 | }); 374 | 375 | asyncTest("Basic colspan table sort column on colspan column", function(){ 376 | var COLSPAN_COLUMN = 1; 377 | var $table = $("#basic-colspan"); 378 | var $table_cols = $table.find("th"); 379 | var $tbody = $table.find("tbody"); 380 | 381 | $table.stupidtable(); 382 | $table_cols.eq(COLSPAN_COLUMN).click(); 383 | 384 | test_table_state(function(){ 385 | var expected = ["X", "Y", "Z"]; 386 | var vals = get_column_elements($table, COLSPAN_COLUMN); 387 | ok(_.isEqual(vals, expected)); 388 | }); 389 | }); 390 | 391 | asyncTest("Complex colspan table sort - single click", function(){ 392 | var NUMBER_COLUMN_TH = 3; 393 | var NUMBER_COLUMN = 3; 394 | var $table = $("#complex-colspan"); 395 | var $table_cols = $table.find("th"); 396 | var $tbody = $table.find("tbody"); 397 | 398 | $table.stupidtable(); 399 | $table_cols.eq(NUMBER_COLUMN_TH).click(); 400 | 401 | test_table_state(function(){ 402 | var expected = ["0", "1", "2"]; 403 | var vals = get_column_elements($table, NUMBER_COLUMN); 404 | ok(_.isEqual(vals, expected)); 405 | }); 406 | }); 407 | 408 | asyncTest("Complex colspan table sort - double click", function(){ 409 | var NUMBER_COLUMN_TH = 3; 410 | var NUMBER_COLUMN = 3; 411 | var $table = $("#complex-colspan"); 412 | var $table_cols = $table.find("th"); 413 | var $tbody = $table.find("tbody"); 414 | 415 | $table.stupidtable(); 416 | $table_cols.eq(NUMBER_COLUMN_TH).doubleclick(); 417 | 418 | test_table_state(function(){ 419 | var expected = ["2", "1", "0"]; 420 | var vals = get_column_elements($table, NUMBER_COLUMN); 421 | ok(_.isEqual(vals, expected)); 422 | }); 423 | }); 424 | 425 | asyncTest("Update sort value - same display and sort values - single click", function(){ 426 | var INT_COLUMN = 0; 427 | var $table = $("#basic"); 428 | var $table_cols = $table.find("th"); 429 | var $int_column = $table_cols.eq(INT_COLUMN); 430 | var $first_int_td = $table.find("tbody tr td").first(); 431 | 432 | $table.stupidtable(); 433 | ok(_.isEqual($first_int_td.text(), "15")); 434 | 435 | $first_int_td.updateSortVal(200); 436 | $first_int_td.text("200"); 437 | $int_column.click(); 438 | 439 | test_table_state(function(){ 440 | var expected = ["-53", "2", "95", "195", "200"]; 441 | var vals = get_column_elements($table, INT_COLUMN); 442 | ok(_.isEqual(vals, expected)); 443 | }); 444 | }); 445 | 446 | asyncTest("Update sort value - same display and sort values - double click", function(){ 447 | var INT_COLUMN = 0; 448 | var $table = $("#basic"); 449 | var $table_cols = $table.find("th"); 450 | var $int_column = $table_cols.eq(INT_COLUMN); 451 | var $first_int_td = $table.find("tbody tr td").first(); 452 | 453 | $table.stupidtable(); 454 | ok(_.isEqual($first_int_td.text(), "15")); 455 | 456 | $first_int_td.updateSortVal(200); 457 | $first_int_td.text("200"); 458 | $int_column.doubleclick(); 459 | 460 | test_table_state(function(){ 461 | var expected = ["200", "195", "95", "2", "-53"]; 462 | var vals = get_column_elements($table, INT_COLUMN); 463 | ok(_.isEqual(vals, expected)); 464 | }); 465 | }); 466 | 467 | asyncTest("Update sort value - different display and sort value - single click", function(){ 468 | var LETTER_FREQ_COLUMN = 5; 469 | var $table = $("#complex"); 470 | var $table_cols = $table.find("th"); 471 | var $letter_freq_col = $table_cols.eq(LETTER_FREQ_COLUMN); 472 | var $e_td = $table.find("[data-sort-value=0]"); 473 | 474 | $table.stupidtable(); 475 | $letter_freq_col.click(); 476 | 477 | ok(_.isEqual($e_td.text(), "E")); 478 | ok(_.isEqual($e_td.data('sort-value'), 0)); 479 | 480 | $e_td.updateSortVal(10); 481 | $e_td.html("YO"); 482 | 483 | 484 | test_table_state(function(){ 485 | var expected = ["T", "A", "O", "I", "YO"]; 486 | var vals = get_column_elements($table, LETTER_FREQ_COLUMN); 487 | ok(_.isEqual(vals, expected)); 488 | }); 489 | }); 490 | 491 | asyncTest("Update sort value - different display and sort value - double click", function(){ 492 | var LETTER_FREQ_COLUMN = 5; 493 | var $table = $("#complex"); 494 | var $table_cols = $table.find("th"); 495 | var $letter_freq_col = $table_cols.eq(LETTER_FREQ_COLUMN); 496 | var $e_td = $table.find("[data-sort-value=0]"); 497 | 498 | $table.stupidtable(); 499 | $letter_freq_col.doubleclick(); 500 | 501 | ok(_.isEqual($e_td.text(), "E")); 502 | ok(_.isEqual($e_td.data('sort-value'), 0)); 503 | 504 | $e_td.updateSortVal(10); 505 | $e_td.html("YO"); 506 | 507 | 508 | test_table_state(function(){ 509 | var expected = ["YO", "I", "O", "A", "T"]; 510 | var vals = get_column_elements($table, LETTER_FREQ_COLUMN); 511 | ok(_.isEqual(vals, expected)); 512 | }); 513 | }); 514 | 515 | asyncTest("Update sort value - also updates data-sort-value attribute", function(){ 516 | var LETTER_FREQ_COLUMN = 5; 517 | var $table = $("#complex"); 518 | var $table_cols = $table.find("th"); 519 | var $letter_freq_col = $table_cols.eq(LETTER_FREQ_COLUMN); 520 | var $e_td = $table.find("[data-sort-value=0]"); 521 | 522 | $table.stupidtable(); 523 | $letter_freq_col.doubleclick(); 524 | 525 | ok(_.isEqual($e_td.text(), "E")); 526 | ok(_.isEqual($e_td.data('sort-value'), 0)); 527 | 528 | $e_td.updateSortVal(10); 529 | $e_td.html("YO"); 530 | 531 | 532 | test_table_state(function(){ 533 | var expected = ["YO", "I", "O", "A", "T"]; 534 | var vals = get_column_elements($table, LETTER_FREQ_COLUMN); 535 | ok(_.isEqual(vals, expected)); 536 | ok(_.isEqual($e_td.attr('data-sort-value'), "10")); 537 | }); 538 | }); 539 | 540 | asyncTest("Update sort value - display value only doesn't add data-sort-value attribute", function(){ 541 | var INT_COLUMN = 0; 542 | var $table = $("#basic"); 543 | var $table_cols = $table.find("th"); 544 | var $int_column = $table_cols.eq(INT_COLUMN); 545 | var $first_int_td = $table.find("tbody tr td").first(); 546 | 547 | $table.stupidtable(); 548 | ok(_.isEqual($first_int_td.text(), "15")); 549 | 550 | $first_int_td.updateSortVal(200); 551 | $first_int_td.text("200"); 552 | $int_column.click(); 553 | 554 | test_table_state(function(){ 555 | var $first_int_td = $table.find("tbody tr td").first(); 556 | var expected = ["-53", "2", "95", "195", "200"]; 557 | var vals = get_column_elements($table, INT_COLUMN); 558 | 559 | ok(_.isEqual(vals, expected)); 560 | ok(!$first_int_td.attr('data-sort-value')); 561 | }); 562 | }); 563 | 564 | asyncTest("Basic individual column sort - no force direction", function(){ 565 | var FLOAT_COLUMN = 1; 566 | var $table = $("#complex"); 567 | var $table_cols = $table.find("th"); 568 | 569 | // Specify a sorting direction 570 | $table_cols.eq(FLOAT_COLUMN).data('sort-default', 'desc'); 571 | $table.stupidtable(); 572 | 573 | $table_cols.eq(FLOAT_COLUMN).stupidsort(); 574 | 575 | test_table_state(function(){ 576 | var expected = ["88.5", "36", "-.18", "-152.5", "-858"]; 577 | var vals = get_column_elements($table, FLOAT_COLUMN); 578 | ok(_.isEqual(vals, expected)); 579 | }); 580 | }); 581 | 582 | asyncTest("Basic individual column sort - force direction", function(){ 583 | var FLOAT_COLUMN = 1; 584 | var $table = $("#complex"); 585 | var $table_cols = $table.find("th"); 586 | 587 | // Specify a sorting direction 588 | $table_cols.eq(FLOAT_COLUMN).data('sort-default', 'desc'); 589 | $table.stupidtable(); 590 | 591 | $table_cols.eq(FLOAT_COLUMN).stupidsort('asc'); 592 | 593 | test_table_state(function(){ 594 | var expected = ["-858", "-152.5", "-.18", "36", "88.5"]; 595 | var vals = get_column_elements($table, FLOAT_COLUMN); 596 | ok(_.isEqual(vals, expected)); 597 | }); 598 | }); 599 | 600 | asyncTest("Sort Stability Testing - 1", function(){ 601 | // Not all browsers implement stable sorting. View the following for more 602 | // information: 603 | // http://ofb.net/~sethml/is-sort-stable.html 604 | // http://codecoding.com/beware-chrome-array-sort-implementation-is-unstable/ 605 | var INDEX_COLUMN = 0; 606 | var LETTER_COLUMN = 1; 607 | var $table = $("#stability-test"); 608 | var $table_cols = $table.find("th"); 609 | 610 | $table.stupidtable(); 611 | $table_cols.eq(LETTER_COLUMN).click(); 612 | 613 | test_table_state(function(){ 614 | var expected = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]; 615 | var vals = get_column_elements($table, INDEX_COLUMN); 616 | ok(_.isEqual(vals, expected)); 617 | }); 618 | }); 619 | 620 | asyncTest("Sort Stability Testing - 2", function(){ 621 | // Not all browsers implement stable sorting. View the following for more 622 | // information: 623 | // http://ofb.net/~sethml/is-sort-stable.html 624 | // http://codecoding.com/beware-chrome-array-sort-implementation-is-unstable/ 625 | var INDEX_COLUMN = 0; 626 | var LETTER_COLUMN = 1; 627 | var $table = $("#stability-test"); 628 | var $table_cols = $table.find("th"); 629 | 630 | $table.stupidtable(); 631 | $table_cols.eq(LETTER_COLUMN).doubleclick(); 632 | 633 | test_table_state(function(){ 634 | var expected = ["10", "9", "8", "7", "6", "5", "4", "3", "2", "1", "0"]; 635 | var vals = get_column_elements($table, INDEX_COLUMN); 636 | ok(_.isEqual(vals, expected)); 637 | }); 638 | }); 639 | 640 | asyncTest("$th passed to after/before tablesort event handlers", function(){ 641 | var INT_COLUMN = 0; 642 | var $table = $("#basic"); 643 | var $table_cols = $table.find("th"); 644 | var $th_objs = []; 645 | 646 | $table.stupidtable(); 647 | var $int_header = $table_cols.eq(INT_COLUMN) 648 | 649 | $table.bind('beforetablesort', function(e, data){ 650 | $th_objs.push(data.$th); 651 | }); 652 | var afterCalls = 0; 653 | $table.bind('aftertablesort', function(e, data){ 654 | $th_objs.push(data.$th); 655 | }); 656 | 657 | $int_header.click(); 658 | 659 | var get_raw_elements = function(arr){ 660 | return _.map(arr, function(el){ 661 | return el[0]; 662 | }); 663 | }; 664 | 665 | test_table_state(function(){ 666 | var expected = get_raw_elements([$int_header, $int_header]); 667 | var raw_th_objs = get_raw_elements($th_objs); 668 | ok(_.isEqual(raw_th_objs, expected)); 669 | }); 670 | }); 671 | 672 | asyncTest("consective calls to stupidsort in same direction should work (issue #183) ", function(){ 673 | var INT_COLUMN = 0; 674 | var $table = $("#basic"); 675 | var $table_cols = $table.find("th"); 676 | var $int_col = $table_cols.eq(INT_COLUMN); 677 | var $e_td = $table.find("[data-sort-value=2]"); 678 | 679 | $table.stupidtable(); 680 | $table_cols.eq(INT_COLUMN).stupidsort($.fn.stupidtable.dir.ASC); 681 | 682 | // Verify we have td with the value 2 in the INT column. 683 | ok(_.isEqual($e_td.text(), "2")); 684 | 685 | setTimeout(function(){ 686 | var newval = -100; 687 | $e_td.updateSortVal(newval); 688 | $e_td.text(newval); 689 | 690 | $table_cols.eq(INT_COLUMN).stupidsort($.fn.stupidtable.dir.ASC); 691 | 692 | 693 | test_table_state(function(){ 694 | var expected = ["-100", "-53", "15", "95", "195"]; 695 | var vals = get_column_elements($table, INT_COLUMN); 696 | ok(_.isEqual(vals, expected)); 697 | }); 698 | 699 | }, window.WAIT_TIME_MS); 700 | }); 701 | 702 | asyncTest("table sorts column onload when specified (issue #180) ", function(){ 703 | var STRING_COLUMN = 2; 704 | var $table = $("#basic-onload"); 705 | var $table_cols = $table.find("th"); 706 | var $str_col = $table_cols.eq(STRING_COLUMN); 707 | 708 | $table.stupidtable(); 709 | 710 | test_table_state(function(){ 711 | var expected = ["apple", "banana", "coke", "orange", "zebra"]; 712 | var vals = get_column_elements($table, STRING_COLUMN); 713 | ok(_.isEqual(vals, expected)); 714 | }); 715 | }); 716 | 717 | asyncTest("test should_redraw setting", function(){ 718 | var INT_COLUMN = 0; 719 | var $table = $("#basic"); 720 | var $table_cols = $table.find("th"); 721 | 722 | $table.stupidtable_settings({ 723 | should_redraw: function(sort_info){ 724 | return false; 725 | } 726 | }); 727 | $table.stupidtable(); 728 | $table_cols.eq(INT_COLUMN).click(); 729 | 730 | test_table_state(function(){ 731 | // Redrawing will never occur so we should expect the initial order to 732 | // be the current column order. 733 | var expected = ["15", "95", "2", "-53", "195"]; 734 | var vals = get_column_elements($table, INT_COLUMN); 735 | ok(_.isEqual(vals, expected)); 736 | }); 737 | }); 738 | 739 | asyncTest("test will_manually_build_table setting - 1", function(){ 740 | var INT_COLUMN = 0; 741 | var $table = $("#basic"); 742 | var $table_cols = $table.find("th"); 743 | var $int_column = $table_cols.eq(INT_COLUMN); 744 | var $first_int_td = $table.find("tbody tr td").first(); 745 | 746 | $table.stupidtable_settings({ 747 | will_manually_build_table: true 748 | }); 749 | $table.stupidtable(); 750 | ok(_.isEqual($first_int_td.text(), "15")); 751 | 752 | $first_int_td.updateSortVal(200); 753 | $first_int_td.text("200"); 754 | $int_column.click(); 755 | 756 | test_table_state(function(){ 757 | // Since we didn't manually build the table after updating the value, we 758 | // shouldn't expect the table to sort correctly. 200 will still function 759 | // as 15 760 | var expected = ["-53", "2", "200", "95", "195"]; 761 | var vals = get_column_elements($table, INT_COLUMN); 762 | ok(_.isEqual(vals, expected)); 763 | }); 764 | }); 765 | 766 | asyncTest("test will_manually_build_table setting - 2", function(){ 767 | var INT_COLUMN = 0; 768 | var $table = $("#basic"); 769 | var $table_cols = $table.find("th"); 770 | var $int_column = $table_cols.eq(INT_COLUMN); 771 | var $first_int_td = $table.find("tbody tr td").first(); 772 | 773 | $table.stupidtable_settings({ 774 | will_manually_build_table: true 775 | }); 776 | $table.stupidtable(); 777 | ok(_.isEqual($first_int_td.text(), "15")); 778 | 779 | $first_int_td.updateSortVal(200); 780 | $first_int_td.text("200"); 781 | 782 | // Rebuild the table 783 | $table.stupidtable_build(); 784 | $int_column.click(); 785 | 786 | test_table_state(function(){ 787 | // Since we didn't manually build the table after updating the value, we 788 | // shouldn't expect the table to sort correctly. 200 will still function 789 | // as 15 790 | var expected = ["-53", "2", "95", "195", "200"]; 791 | var vals = get_column_elements($table, INT_COLUMN); 792 | ok(_.isEqual(vals, expected)); 793 | }); 794 | }); 795 | 796 | asyncTest("test will_manually_build_table setting - 3", function(){ 797 | var INT_COLUMN = 0; 798 | var $table = $("#basic"); 799 | var $table_cols = $table.find("th"); 800 | var $int_column = $table_cols.eq(INT_COLUMN); 801 | var $first_int_td = $table.find("tbody tr td").first(); 802 | 803 | $table.stupidtable_settings({ 804 | will_manually_build_table: false 805 | }); 806 | $table.stupidtable(); 807 | ok(_.isEqual($first_int_td.text(), "15")); 808 | 809 | $first_int_td.updateSortVal(200); 810 | $first_int_td.text("200"); 811 | $int_column.click(); 812 | 813 | test_table_state(function(){ 814 | // Since we didn't manually build the table after updating the value, we 815 | // shouldn't expect the table to sort correctly. 200 will still function 816 | // as 15 817 | var expected = ["-53", "2", "95", "195", "200"]; 818 | var vals = get_column_elements($table, INT_COLUMN); 819 | ok(_.isEqual(vals, expected)); 820 | }); 821 | }); 822 | 823 | test("Multicolumn table initial order", function(){ 824 | var INT_COLUMN = 0; 825 | var FLOAT_COLUMN = 1; 826 | var STRING_COLUMN = 2; 827 | var expected; 828 | var vals; 829 | 830 | var $table = $("#multicolumn-sort-test"); 831 | 832 | expected = ["1", "1", "2", "0", "1", "2", "0", "0", "0", "1", "2", "3", "2"]; 833 | vals = get_column_elements($table, INT_COLUMN); 834 | ok(_.isEqual(vals, expected)); 835 | 836 | expected = ["10.0", "10.0", "10.0", "20.0", "30.0", "30.0", "10.0", "20.0", "10.0", "20.0", "10.0", "30.0", "30.0"]; 837 | vals = get_column_elements($table, FLOAT_COLUMN); 838 | ok(_.isEqual(vals, expected)); 839 | 840 | expected = ["a", "a", "b", "c", "b", "a", "b", "a", "c", "a", "b", "a", "b"]; 841 | vals = get_column_elements($table, STRING_COLUMN); 842 | ok(_.isEqual(vals, expected)); 843 | 844 | }); 845 | 846 | asyncTest("Basic multicolumn sort", function(){ 847 | var INT_COLUMN = 0; 848 | var FLOAT_COLUMN = 1; 849 | var STRING_COLUMN = 2; 850 | var $table = $("#multicolumn-sort-test"); 851 | var $table_cols = $table.find("th"); 852 | 853 | $table.stupidtable(); 854 | $table_cols.eq(INT_COLUMN).click(); 855 | 856 | test_table_state(function(){ 857 | var expected; 858 | var vals; 859 | 860 | expected = ["0", "0", "0", "0", "1", "1", "1", "1", "2", "2", "2", "2", "3"]; 861 | vals = get_column_elements($table, INT_COLUMN); 862 | ok(_.isEqual(vals, expected)); 863 | 864 | expected = ["10.0", "10.0", "20.0", "20.0", "10.0", "10.0", "20.0", "30.0", "10.0", "10.0", "30.0", "30.0", "30.0"]; 865 | vals = get_column_elements($table, FLOAT_COLUMN); 866 | ok(_.isEqual(vals, expected)); 867 | 868 | expected = ["b", "c", "a", "c", "a", "a", "a", "b", "b", "b", "a", "b", "a"]; 869 | vals = get_column_elements($table, STRING_COLUMN); 870 | ok(_.isEqual(vals, expected)); 871 | }); 872 | }); 873 | 874 | }); //jQuery 875 | -------------------------------------------------------------------------------- /tests/underscore.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.5.2 2 | // http://underscorejs.org 3 | // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 4 | // Underscore may be freely distributed under the MIT license. 5 | (function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?(this._wrapped=n,void 0):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.5.2";var A=j.each=j.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var E="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(E);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(E);return r},j.find=j.detect=function(n,t,r){var e;return O(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var O=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:O(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,function(n){return n[t]})},j.where=function(n,t,r){return j.isEmpty(t)?r?void 0:[]:j[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},j.findWhere=function(n,t){return j.where(n,t,!0)},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);if(!t&&j.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>e.computed&&(e={value:n,computed:a})}),e.value},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);if(!t&&j.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;ae||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={},i=null==r?j.identity:k(r);return A(t,function(r,a){var o=i.call(e,r,a,t);n(u,o,r)}),u}};j.groupBy=F(function(n,t,r){(j.has(n,t)?n[t]:n[t]=[]).push(r)}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=null==r?j.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])=0})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},j.bindAll=function(n){var t=o.call(arguments,1);if(0===t.length)throw new Error("bindAll must be passed function names");return A(t,function(t){n[t]=j.bind(n[t],n)}),n},j.memoize=function(n,t){var r={};return t||(t=j.identity),function(){var e=t.apply(this,arguments);return j.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},j.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},j.defer=function(n){return j.delay.apply(j,[n,1].concat(o.call(arguments,1)))},j.throttle=function(n,t,r){var e,u,i,a=null,o=0;r||(r={});var c=function(){o=r.leading===!1?0:new Date,a=null,i=n.apply(e,u)};return function(){var l=new Date;o||r.leading!==!1||(o=l);var f=t-(l-o);return e=this,u=arguments,0>=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u)):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o;return function(){i=this,u=arguments,a=new Date;var c=function(){var l=new Date-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u)))},l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u)),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=w||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=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 j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(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;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o))return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var I={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};I.unescape=j.invert(I.escape);var T={escape:new RegExp("["+j.keys(I.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(I.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(T[n],function(t){return I[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); 6 | //# sourceMappingURL=underscore-min.map --------------------------------------------------------------------------------