Index: trunk/phase3/resources/jquery/jquery.tablesorter.js |
— | — | @@ -1,37 +1,38 @@ |
2 | | -/* |
3 | | - * |
| 2 | +/** |
4 | 3 | * TableSorter for MediaWiki |
5 | | - * |
| 4 | + * |
6 | 5 | * Written 2011 Leo Koppelkamm |
7 | 6 | * Based on tablesorter.com plugin, written (c) 2007 Christian Bach. |
8 | 7 | * |
9 | 8 | * Dual licensed under the MIT and GPL licenses: |
10 | 9 | * http://www.opensource.org/licenses/mit-license.php |
11 | 10 | * http://www.gnu.org/licenses/gpl.html |
12 | | - * |
| 11 | + * |
| 12 | + * @depends on mw.config (wgDigitTransformTable, wgMonthNames, wgMonthNamesShort, |
| 13 | + * wgDefaultDateFormat, wgContentLanguage) |
13 | 14 | */ |
14 | 15 | /** |
15 | | - * |
| 16 | + * |
16 | 17 | * @description Create a sortable table with multi-column sorting capabilitys |
17 | | - * |
| 18 | + * |
18 | 19 | * @example $( 'table' ).tablesorter(); |
19 | 20 | * @desc Create a simple tablesorter interface. |
20 | 21 | * |
21 | 22 | * @option String cssHeader ( optional ) A string of the class name to be appended |
22 | 23 | * to sortable tr elements in the thead of the table. Default value: |
23 | 24 | * "header" |
24 | | - * |
| 25 | + * |
25 | 26 | * @option String cssAsc ( optional ) A string of the class name to be appended to |
26 | 27 | * sortable tr elements in the thead on a ascending sort. Default value: |
27 | 28 | * "headerSortUp" |
28 | | - * |
| 29 | + * |
29 | 30 | * @option String cssDesc ( optional ) A string of the class name to be appended |
30 | 31 | * to sortable tr elements in the thead on a descending sort. Default |
31 | 32 | * value: "headerSortDown" |
32 | | - * |
| 33 | + * |
33 | 34 | * @option String sortInitialOrder ( optional ) A string of the inital sorting |
34 | 35 | * order can be asc or desc. Default value: "asc" |
35 | | - * |
| 36 | + * |
36 | 37 | * @option String sortMultisortKey ( optional ) A string of the multi-column sort |
37 | 38 | * key. Default value: "shiftKey" |
38 | 39 | * |
— | — | @@ -41,525 +42,534 @@ |
42 | 43 | * @option Boolean cancelSelection ( optional ) Boolean flag indicating if |
43 | 44 | * tablesorter should cancel selection of the table headers text. |
44 | 45 | * Default value: true |
45 | | - * |
| 46 | + * |
46 | 47 | * @option Boolean debug ( optional ) Boolean flag indicating if tablesorter |
47 | 48 | * should display debuging information usefull for development. |
48 | | - * |
| 49 | + * |
49 | 50 | * @type jQuery |
50 | | - * |
| 51 | + * |
51 | 52 | * @name tablesorter |
52 | | - * |
| 53 | + * |
53 | 54 | * @cat Plugins/Tablesorter |
54 | | - * |
| 55 | + * |
55 | 56 | * @author Christian Bach/christian.bach@polyester.se |
56 | 57 | */ |
57 | 58 | |
58 | | -( function ($) { |
59 | | - $.extend( { |
60 | | - tablesorter: new |
| 59 | +( function( $ ) { |
61 | 60 | |
62 | | - function () { |
| 61 | + /* Local scope */ |
63 | 62 | |
64 | | - var parsers = []; |
| 63 | + var ts, |
| 64 | + parsers = []; |
65 | 65 | |
66 | | - this.defaults = { |
67 | | - cssHeader: "headerSort", |
68 | | - cssAsc: "headerSortUp", |
69 | | - cssDesc: "headerSortDown", |
70 | | - cssChildRow: "expand-child", |
71 | | - sortInitialOrder: "asc", |
72 | | - sortMultiSortKey: "shiftKey", |
73 | | - sortLocaleCompare: false, |
74 | | - parsers: {}, |
75 | | - widgets: [], |
76 | | - headers: {}, |
77 | | - cancelSelection: true, |
78 | | - sortList: [], |
79 | | - headerList: [], |
80 | | - selectorHeaders: 'thead tr:eq(0) th', |
81 | | - debug: false |
82 | | - }; |
| 66 | + /* Parser utility functions */ |
83 | 67 | |
84 | | - /* parsers utils */ |
| 68 | + function getParserById( name ) { |
| 69 | + var len = parsers.length; |
| 70 | + for ( var i = 0; i < len; i++ ) { |
| 71 | + if ( parsers[i].id.toLowerCase() === name.toLowerCase() ) { |
| 72 | + return parsers[i]; |
| 73 | + } |
| 74 | + } |
| 75 | + return false; |
| 76 | + } |
85 | 77 | |
86 | | - function buildParserCache( table, $headers ) { |
87 | | - var rows = table.tBodies[0].rows, |
88 | | - sortType; |
| 78 | + function getElementText( node ) { |
| 79 | + if ( node.hasAttribute && node.hasAttribute( 'data-sort-value' ) ) { |
| 80 | + return node.getAttribute( 'data-sort-value' ); |
| 81 | + } else { |
| 82 | + return $( node ).text(); |
| 83 | + } |
| 84 | + } |
89 | 85 | |
90 | | - if ( rows[0] ) { |
| 86 | + function getTextFromRowAndCellIndex( rows, rowIndex, cellIndex ) { |
| 87 | + if ( rows[rowIndex] && rows[rowIndex].cells[cellIndex] ) { |
| 88 | + return $.trim( getElementText( rows[rowIndex].cells[cellIndex] ) ); |
| 89 | + } else { |
| 90 | + return ''; |
| 91 | + } |
| 92 | + } |
91 | 93 | |
92 | | - var list = [], |
93 | | - cells = rows[0].cells, |
94 | | - l = cells.length; |
| 94 | + function detectParserForColumn( table, rows, cellIndex ) { |
| 95 | + var l = parsers.length, |
| 96 | + nodeValue, |
| 97 | + // Start with 1 because 0 is the fallback parser |
| 98 | + i = 1, |
| 99 | + rowIndex = 0, |
| 100 | + concurrent = 0, |
| 101 | + needed = ( rows.length > 4 ) ? 5 : rows.length; |
95 | 102 | |
96 | | - for ( var i = 0; i < l; i++ ) { |
97 | | - var p = false; |
98 | | - sortType = $headers.eq(i).data('sort-type'); |
99 | | - if ( typeof sortType != 'undefined' ) { |
100 | | - p = getParserById( sortType ); |
101 | | - } |
102 | | - |
103 | | - if (p === false) { |
104 | | - p = detectParserForColumn( table, rows, i ); |
105 | | - } |
106 | | - |
107 | | - list.push(p); |
| 103 | + while( i < l ) { |
| 104 | + nodeValue = getTextFromRowAndCellIndex( rows, rowIndex, cellIndex ); |
| 105 | + if ( nodeValue !== '') { |
| 106 | + if ( parsers[i].is( nodeValue, table ) ) { |
| 107 | + concurrent++; |
| 108 | + rowIndex++; |
| 109 | + if ( concurrent >= needed ) { |
| 110 | + // Confirmed the parser for multiple cells, let's return it |
| 111 | + return parsers[i]; |
108 | 112 | } |
109 | | - } |
110 | | - return list; |
111 | | - } |
112 | | - |
113 | | - function detectParserForColumn( table, rows, cellIndex ) { |
114 | | - var l = parsers.length, |
115 | | - nodeValue, |
116 | | - // Start with 1 because 0 is the fallback parser |
117 | | - i = 1, |
118 | | - rowIndex = 0, |
119 | | - concurrent = 0, |
120 | | - needed = (rows.length > 4 ) ? 5 : rows.length; |
121 | | - while( i<l ) { |
122 | | - nodeValue = getTextFromRowAndCellIndex( rows, rowIndex, cellIndex ); |
123 | | - if ( nodeValue != '') { |
124 | | - if ( parsers[i].is( nodeValue, table ) ) { |
125 | | - concurrent++; |
126 | | - rowIndex++; |
127 | | - if (concurrent >= needed ) { |
128 | | - // Confirmed the parser for multiple cells, let's return it |
129 | | - return parsers[i]; |
130 | | - } |
131 | | - } else { |
132 | | - // Check next parser, reset rows |
133 | | - i++; |
134 | | - rowIndex = 0; |
135 | | - concurrent = 0; |
136 | | - } |
137 | | - } else { |
138 | | - // Empty cell |
139 | | - rowIndex++; |
140 | | - if ( rowIndex > rows.length ) { |
141 | | - rowIndex = 0; |
142 | | - i++; |
143 | | - } |
144 | | - } |
145 | | - } |
146 | | - |
147 | | - // 0 is always the generic parser ( text ) |
148 | | - return parsers[0]; |
149 | | - } |
150 | | - |
151 | | - function getTextFromRowAndCellIndex( rows, rowIndex, cellIndex ) { |
152 | | - if ( rows[rowIndex] && rows[rowIndex].cells[cellIndex] ) { |
153 | | - return $.trim( getElementText( rows[rowIndex].cells[cellIndex] ) ); |
154 | 113 | } else { |
155 | | - return ''; |
| 114 | + // Check next parser, reset rows |
| 115 | + i++; |
| 116 | + rowIndex = 0; |
| 117 | + concurrent = 0; |
156 | 118 | } |
157 | | - } |
158 | | - |
159 | | - function getParserById( name ) { |
160 | | - var l = parsers.length; |
161 | | - for ( var i = 0; i < l; i++ ) { |
162 | | - if ( parsers[i].id.toLowerCase() == name.toLowerCase() ) { |
163 | | - return parsers[i]; |
164 | | - } |
| 119 | + } else { |
| 120 | + // Empty cell |
| 121 | + rowIndex++; |
| 122 | + if ( rowIndex > rows.length ) { |
| 123 | + rowIndex = 0; |
| 124 | + i++; |
165 | 125 | } |
166 | | - return false; |
167 | 126 | } |
| 127 | + } |
168 | 128 | |
169 | | - /* utils */ |
| 129 | + // 0 is always the generic parser (text) |
| 130 | + return parsers[0]; |
| 131 | + } |
170 | 132 | |
171 | | - function buildCache( table ) { |
172 | | - // if ( table.config.debug ) { |
173 | | - // var cacheTime = new Date(); |
174 | | - // } |
175 | | - var totalRows = ( table.tBodies[0] && table.tBodies[0].rows.length ) || 0, |
176 | | - totalCells = ( table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length ) || 0, |
177 | | - parsers = table.config.parsers, |
178 | | - cache = { |
179 | | - row: [], |
180 | | - normalized: [] |
181 | | - }; |
| 133 | + function buildParserCache( table, $headers ) { |
| 134 | + var rows = table.tBodies[0].rows, |
| 135 | + sortType, |
| 136 | + parsers = []; |
182 | 137 | |
183 | | - for ( var i = 0; i < totalRows; ++i ) { |
| 138 | + if ( rows[0] ) { |
184 | 139 | |
185 | | - // Add the table data to main data array |
186 | | - var c = $( table.tBodies[0].rows[i] ), |
187 | | - cols = []; |
| 140 | + var cells = rows[0].cells, |
| 141 | + len = cells.length, |
| 142 | + i, parser; |
188 | 143 | |
189 | | - // if this is a child row, add it to the last row's children and |
190 | | - // continue to the next row |
191 | | - if ( c.hasClass( table.config.cssChildRow ) ) { |
192 | | - cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add(c); |
193 | | - // go to the next for loop |
194 | | - continue; |
195 | | - } |
| 144 | + for ( i = 0; i < len; i++ ) { |
| 145 | + parser = false; |
| 146 | + sortType = $headers.eq( i ).data( 'sort-type' ); |
| 147 | + if ( sortType !== undefined ) { |
| 148 | + parser = getParserById( sortType ); |
| 149 | + } |
196 | 150 | |
197 | | - cache.row.push(c); |
| 151 | + if ( parser === false ) { |
| 152 | + parser = detectParserForColumn( table, rows, i ); |
| 153 | + } |
198 | 154 | |
199 | | - for ( var j = 0; j < totalCells; ++j ) { |
200 | | - cols.push( parsers[j].format( getElementText( c[0].cells[j] ), table, c[0].cells[j] ) ); |
201 | | - } |
| 155 | + parsers.push( parser ); |
| 156 | + } |
| 157 | + } |
| 158 | + return parsers; |
| 159 | + } |
202 | 160 | |
203 | | - cols.push( cache.normalized.length ); // add position for rowCache |
204 | | - cache.normalized.push( cols ); |
205 | | - cols = null; |
206 | | - } |
| 161 | + /* Other utility functions */ |
207 | 162 | |
208 | | - // if ( table.config.debug ) { |
209 | | - // benchmark( "Building cache for " + totalRows + " rows:", cacheTime ); |
210 | | - // } |
211 | | - return cache; |
| 163 | + function buildCache( table ) { |
| 164 | + var totalRows = ( table.tBodies[0] && table.tBodies[0].rows.length ) || 0, |
| 165 | + totalCells = ( table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length ) || 0, |
| 166 | + parsers = table.config.parsers, |
| 167 | + cache = { |
| 168 | + row: [], |
| 169 | + normalized: [] |
| 170 | + }; |
| 171 | + |
| 172 | + for ( var i = 0; i < totalRows; ++i ) { |
| 173 | + |
| 174 | + // Add the table data to main data array |
| 175 | + var $row = $( table.tBodies[0].rows[i] ), |
| 176 | + cols = []; |
| 177 | + |
| 178 | + // if this is a child row, add it to the last row's children and |
| 179 | + // continue to the next row |
| 180 | + if ( $row.hasClass( table.config.cssChildRow ) ) { |
| 181 | + cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add( $row ); |
| 182 | + // go to the next for loop |
| 183 | + continue; |
212 | 184 | } |
213 | 185 | |
214 | | - function getElementText( node ) { |
215 | | - if ( node.hasAttribute && node.hasAttribute( "data-sort-value" ) ) { |
216 | | - return node.getAttribute( "data-sort-value" ); |
217 | | - } else { |
218 | | - return $( node ).text(); |
219 | | - } |
| 186 | + cache.row.push( $row ); |
| 187 | + |
| 188 | + for ( var j = 0; j < totalCells; ++j ) { |
| 189 | + cols.push( parsers[j].format( getElementText( $row[0].cells[j] ), table, $row[0].cells[j] ) ); |
220 | 190 | } |
221 | 191 | |
222 | | - function appendToTable( table, cache ) { |
223 | | - // if ( table.config.debug ) { |
224 | | - // var appendTime = new Date() |
225 | | - // } |
226 | | - var c = cache, |
227 | | - r = c.row, |
228 | | - n = c.normalized, |
229 | | - totalRows = n.length, |
230 | | - checkCell = (n[0].length - 1), |
231 | | - tableBody = $( table.tBodies[0] ), |
232 | | - fragment = document.createDocumentFragment(); |
| 192 | + cols.push( cache.normalized.length ); // add position for rowCache |
| 193 | + cache.normalized.push( cols ); |
| 194 | + cols = null; |
| 195 | + } |
233 | 196 | |
234 | | - for ( var i = 0; i < totalRows; i++ ) { |
235 | | - var pos = n[i][checkCell]; |
| 197 | + return cache; |
| 198 | + } |
236 | 199 | |
237 | | - var l = r[pos].length; |
| 200 | + function appendToTable( table, cache ) { |
| 201 | + var row = cache.row, |
| 202 | + normalized = cache.normalized, |
| 203 | + totalRows = normalized.length, |
| 204 | + checkCell = ( normalized[0].length - 1 ), |
| 205 | + fragment = document.createDocumentFragment(); |
238 | 206 | |
239 | | - for ( var j = 0; j < l; j++ ) { |
240 | | - fragment.appendChild( r[pos][j] ); |
241 | | - } |
| 207 | + for ( var i = 0; i < totalRows; i++ ) { |
| 208 | + var pos = normalized[i][checkCell]; |
242 | 209 | |
243 | | - } |
244 | | - tableBody[0].appendChild( fragment ); |
245 | | - // if ( table.config.debug ) { |
246 | | - // benchmark( "Rebuilt table:", appendTime ); |
247 | | - // } |
| 210 | + var l = row[pos].length; |
| 211 | + |
| 212 | + for ( var j = 0; j < l; j++ ) { |
| 213 | + fragment.appendChild( row[pos][j] ); |
248 | 214 | } |
249 | 215 | |
250 | | - function buildHeaders( table, msg ) { |
251 | | - var maxSeen = 0; |
252 | | - var longest; |
253 | | - // if ( table.config.debug ) { |
254 | | - // var time = new Date(); |
255 | | - // } |
256 | | - //var header_index = computeTableHeaderCellIndexes( table ); |
257 | | - var realCellIndex = 0; |
258 | | - var $tableHeaders = $( "thead:eq(0) tr", table ); |
259 | | - if ( $tableHeaders.length > 1 ) { |
260 | | - $tableHeaders.each(function() { |
261 | | - if (this.cells.length > maxSeen) { |
262 | | - maxSeen = this.cells.length; |
263 | | - longest = this; |
264 | | - } |
265 | | - }); |
266 | | - $tableHeaders = $( longest ); |
| 216 | + } |
| 217 | + table.tBodies[0].appendChild( fragment ); |
| 218 | + } |
| 219 | + |
| 220 | + function buildHeaders( table, msg ) { |
| 221 | + var maxSeen = 0, |
| 222 | + longest, |
| 223 | + realCellIndex = 0, |
| 224 | + $tableHeaders = $( 'thead:eq(0) tr', table ); |
| 225 | + if ( $tableHeaders.length > 1 ) { |
| 226 | + $tableHeaders.each(function() { |
| 227 | + if ( this.cells.length > maxSeen ) { |
| 228 | + maxSeen = this.cells.length; |
| 229 | + longest = this; |
267 | 230 | } |
268 | | - $tableHeaders = $tableHeaders.find('th').each( function ( index ) { |
269 | | - //var normalIndex = allCells.index( this ); |
270 | | - //var realCellIndex = 0; |
271 | | - this.column = realCellIndex; |
| 231 | + }); |
| 232 | + $tableHeaders = $( longest ); |
| 233 | + } |
| 234 | + $tableHeaders = $tableHeaders.find( 'th' ).each( function( index ) { |
| 235 | + this.column = realCellIndex; |
272 | 236 | |
273 | | - var colspan = this.colspan; |
274 | | - colspan = colspan ? parseInt( colspan, 10 ) : 1; |
275 | | - realCellIndex += colspan; |
| 237 | + var colspan = this.colspan; |
| 238 | + colspan = colspan ? parseInt( colspan, 10 ) : 1; |
| 239 | + realCellIndex += colspan; |
276 | 240 | |
277 | | - //this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex]; |
278 | | - this.order = 0; |
279 | | - this.count = 0; |
| 241 | + this.order = 0; |
| 242 | + this.count = 0; |
280 | 243 | |
281 | | - if ( $( this ).is( '.unsortable, .mw-unsortable' ) ) this.sortDisabled = true; |
| 244 | + if ( $( this ).is( '.unsortable, .mw-unsortable' ) ) { |
| 245 | + this.sortDisabled = true; |
| 246 | + } |
282 | 247 | |
283 | | - if ( !this.sortDisabled ) { |
284 | | - var $th = $( this ).addClass( table.config.cssHeader ).attr( 'title', msg[1] ); |
285 | | - |
286 | | - //if ( table.config.onRenderHeader ) table.config.onRenderHeader.apply($th); |
287 | | - } |
| 248 | + if ( !this.sortDisabled ) { |
| 249 | + var $th = $( this ).addClass( table.config.cssHeader ).attr( 'title', msg[1] ); |
| 250 | + } |
288 | 251 | |
289 | | - // add cell to headerList |
290 | | - table.config.headerList[index] = this; |
291 | | - } ); |
| 252 | + // add cell to headerList |
| 253 | + table.config.headerList[index] = this; |
| 254 | + } ); |
292 | 255 | |
293 | | - return $tableHeaders; |
| 256 | + return $tableHeaders; |
294 | 257 | |
| 258 | + } |
| 259 | + |
| 260 | + function isValueInArray( v, a ) { |
| 261 | + var l = a.length; |
| 262 | + for ( var i = 0; i < l; i++ ) { |
| 263 | + if ( a[i][0] == v ) { |
| 264 | + return true; |
295 | 265 | } |
| 266 | + } |
| 267 | + return false; |
| 268 | + } |
296 | 269 | |
297 | | - function isValueInArray( v, a ) { |
298 | | - var l = a.length; |
299 | | - for ( var i = 0; i < l; i++ ) { |
300 | | - if ( a[i][0] == v ) { |
301 | | - return true; |
302 | | - } |
303 | | - } |
304 | | - return false; |
| 270 | + function setHeadersCss( table, $headers, list, css, msg ) { |
| 271 | + // Remove all header information |
| 272 | + $headers.removeClass( css[0] ).removeClass( css[1] ); |
| 273 | + |
| 274 | + var h = []; |
| 275 | + $headers.each( function( offset ) { |
| 276 | + if ( !this.sortDisabled ) { |
| 277 | + h[this.column] = $( this ); |
305 | 278 | } |
| 279 | + } ); |
306 | 280 | |
307 | | - function setHeadersCss( table, $headers, list, css, msg ) { |
308 | | - // remove all header information |
309 | | - $headers.removeClass( css[0] ).removeClass( css[1] ); |
| 281 | + var l = list.length; |
| 282 | + for ( var i = 0; i < l; i++ ) { |
| 283 | + h[ list[i][0] ].addClass( css[ list[i][1] ] ).attr( 'title', msg[ list[i][1] ] ); |
| 284 | + } |
| 285 | + } |
310 | 286 | |
311 | | - var h = []; |
312 | | - $headers.each( function ( offset ) { |
313 | | - if ( !this.sortDisabled ) { |
314 | | - h[this.column] = $( this ); |
315 | | - } |
316 | | - } ); |
| 287 | + function sortText( a, b ) { |
| 288 | + return ( (a < b) ? false : ((a > b) ? true : 0) ); |
| 289 | + } |
317 | 290 | |
318 | | - var l = list.length; |
319 | | - for ( var i = 0; i < l; i++ ) { |
320 | | - h[ list[i][0] ].addClass( css[ list[i][1] ] ).attr( 'title', msg[ list[i][1] ] ); |
321 | | - } |
322 | | - } |
| 291 | + function sortTextDesc( a, b ) { |
| 292 | + return ( (b < a) ? false : ((b > a) ? true : 0) ); |
| 293 | + } |
323 | 294 | |
324 | | - function checkSorting (array1, array2, sortList) { |
325 | | - var col, fn, ret; |
326 | | - for ( var i = 0, len = sortList.length; i < len; i++ ) { |
327 | | - col = sortList[i][0]; |
328 | | - fn = ( sortList[i][1] ) ? sortTextDesc : sortText; |
329 | | - ret = fn.call( this, array1[col], array2[col] ); |
330 | | - if ( ret !== 0 ) { |
331 | | - return ret; |
332 | | - } |
333 | | - } |
| 295 | + function checkSorting( array1, array2, sortList ) { |
| 296 | + var col, fn, ret; |
| 297 | + for ( var i = 0, len = sortList.length; i < len; i++ ) { |
| 298 | + col = sortList[i][0]; |
| 299 | + fn = ( sortList[i][1] ) ? sortTextDesc : sortText; |
| 300 | + ret = fn.call( this, array1[col], array2[col] ); |
| 301 | + if ( ret !== 0 ) { |
334 | 302 | return ret; |
335 | 303 | } |
| 304 | + } |
| 305 | + return ret; |
| 306 | + } |
336 | 307 | |
337 | | - // Merge sort algorithm |
338 | | - // Based on http://en.literateprograms.org/Merge_sort_(JavaScript) |
339 | | - function mergeSortHelper(array, begin, beginRight, end, sortList) { |
340 | | - for (; begin < beginRight; ++begin) { |
341 | | - if (checkSorting( array[begin], array[beginRight], sortList )) { |
342 | | - var v = array[begin]; |
343 | | - array[begin] = array[beginRight]; |
344 | | - var begin2 = beginRight; |
345 | | - while ( begin2 + 1 < end && checkSorting( v, array[begin2 + 1], sortList ) ) { |
346 | | - var tmp = array[begin2]; |
347 | | - array[begin2] = array[begin2 + 1]; |
348 | | - array[begin2 + 1] = tmp; |
349 | | - ++begin2; |
350 | | - } |
351 | | - array[begin2] = v; |
352 | | - } |
| 308 | + // Merge sort algorithm |
| 309 | + // Based on http://en.literateprograms.org/Merge_sort_(JavaScript) |
| 310 | + function mergeSortHelper( array, begin, beginRight, end, sortList ) { |
| 311 | + for ( ; begin < beginRight; ++begin ) { |
| 312 | + if ( checkSorting( array[begin], array[beginRight], sortList ) ) { |
| 313 | + var v = array[begin]; |
| 314 | + array[begin] = array[beginRight]; |
| 315 | + var begin2 = beginRight; |
| 316 | + while ( begin2 + 1 < end && checkSorting( v, array[begin2 + 1], sortList ) ) { |
| 317 | + var tmp = array[begin2]; |
| 318 | + array[begin2] = array[begin2 + 1]; |
| 319 | + array[begin2 + 1] = tmp; |
| 320 | + ++begin2; |
353 | 321 | } |
| 322 | + array[begin2] = v; |
354 | 323 | } |
| 324 | + } |
| 325 | + } |
355 | 326 | |
356 | | - function mergeSort(array, begin, end, sortList) { |
357 | | - var size = end - begin; |
358 | | - if (size < 2) return; |
| 327 | + function mergeSort(array, begin, end, sortList) { |
| 328 | + var size = end - begin; |
| 329 | + if ( size < 2 ) { |
| 330 | + return; |
| 331 | + } |
359 | 332 | |
360 | | - var beginRight = begin + Math.floor(size / 2); |
| 333 | + var beginRight = begin + Math.floor(size / 2); |
361 | 334 | |
362 | | - mergeSort(array, begin, beginRight, sortList); |
363 | | - mergeSort(array, beginRight, end, sortList); |
364 | | - mergeSortHelper(array, begin, beginRight, end, sortList); |
365 | | - } |
| 335 | + mergeSort( array, begin, beginRight, sortList ); |
| 336 | + mergeSort( array, beginRight, end, sortList ); |
| 337 | + mergeSortHelper( array, begin, beginRight, end, sortList ); |
| 338 | + } |
366 | 339 | |
367 | | - function multisort( table, sortList, cache ) { |
368 | | - //var sortTime = new Date(); |
369 | | - |
370 | | - var i = sortList.length; |
371 | | - mergeSort(cache.normalized, 0, cache.normalized.length, sortList); |
| 340 | + function multisort( table, sortList, cache ) { |
| 341 | + var i = sortList.length; |
| 342 | + mergeSort( cache.normalized, 0, cache.normalized.length, sortList ); |
372 | 343 | |
373 | | - //benchmark( "Sorting in dir " + order + " time:", sortTime ); |
374 | | - |
375 | | - return cache; |
376 | | - } |
| 344 | + return cache; |
| 345 | + } |
377 | 346 | |
378 | | - function sortText( a, b ) { |
379 | | - return ((a < b) ? false : ((a > b) ? true : 0)); |
380 | | - } |
| 347 | + function buildTransformTable() { |
| 348 | + var digits = '0123456789,.'.split( '' ); |
| 349 | + var separatorTransformTable = mw.config.get( 'wgSeparatorTransformTable' ); |
| 350 | + var digitTransformTable = mw.config.get( 'wgDigitTransformTable' ); |
| 351 | + if ( separatorTransformTable === null || ( separatorTransformTable[0] === '' && digitTransformTable[2] === '' ) ) { |
| 352 | + ts.transformTable = false; |
| 353 | + } else { |
| 354 | + ts.transformTable = {}; |
381 | 355 | |
382 | | - function sortTextDesc( a, b ) { |
383 | | - return ((b < a) ? false : ((b > a) ? true : 0)); |
| 356 | + // Unpack the transform table |
| 357 | + var ascii = separatorTransformTable[0].split( "\t" ).concat( digitTransformTable[0].split( "\t" ) ); |
| 358 | + var localised = separatorTransformTable[1].split( "\t" ).concat( digitTransformTable[1].split( "\t" ) ); |
| 359 | + |
| 360 | + // Construct regex for number identification |
| 361 | + for ( var i = 0; i < ascii.length; i++ ) { |
| 362 | + ts.transformTable[localised[i]] = ascii[i]; |
| 363 | + digits.push( $.escapeRE( localised[i] ) ); |
384 | 364 | } |
| 365 | + } |
| 366 | + var digitClass = '[' + digits.join( '', digits ) + ']'; |
385 | 367 | |
386 | | - function buildTransformTable() { |
387 | | - var digits = '0123456789,.'.split(''); |
388 | | - var separatorTransformTable = mw.config.get( 'wgSeparatorTransformTable' ); |
389 | | - var digitTransformTable = mw.config.get( 'wgDigitTransformTable' ); |
390 | | - if ( separatorTransformTable == null || ( separatorTransformTable[0] == '' && digitTransformTable[2] == '' ) ) { |
391 | | - ts.transformTable = false; |
392 | | - } else { |
393 | | - ts.transformTable = {}; |
| 368 | + // We allow a trailing percent sign, which we just strip. This works fine |
| 369 | + // if percents and regular numbers aren't being mixed. |
| 370 | + ts.numberRegex = new RegExp("^(" + "[-+\u2212]?[0-9][0-9,]*(\\.[0-9,]*)?(E[-+\u2212]?[0-9][0-9,]*)?" + // Fortran-style scientific |
| 371 | + "|" + "[-+\u2212]?" + digitClass + "+[\\s\\xa0]*%?" + // Generic localised |
| 372 | + ")$", "i"); |
| 373 | + } |
394 | 374 | |
395 | | - // Unpack the transform table |
396 | | - var ascii = separatorTransformTable[0].split( "\t" ).concat( digitTransformTable[0].split( "\t" ) ); |
397 | | - var localised = separatorTransformTable[1].split( "\t" ).concat( digitTransformTable[1].split( "\t" ) ); |
| 375 | + function buildDateTable() { |
| 376 | + var regex = []; |
| 377 | + ts.monthNames = [ |
| 378 | + [], |
| 379 | + [] |
| 380 | + ]; |
398 | 381 | |
399 | | - // Construct regex for number identification |
400 | | - for ( var i = 0; i < ascii.length; i++ ) { |
401 | | - ts.transformTable[localised[i]] = ascii[i]; |
402 | | - digits.push( $.escapeRE( localised[i] ) ); |
403 | | - } |
404 | | - } |
405 | | - var digitClass = '[' + digits.join( '', digits ) + ']'; |
| 382 | + for ( var i = 1; i < 13; i++ ) { |
| 383 | + ts.monthNames[0][i] = mw.config.get( 'wgMonthNames' )[i].toLowerCase(); |
| 384 | + ts.monthNames[1][i] = mw.config.get( 'wgMonthNamesShort' )[i].toLowerCase().replace( '.', '' ); |
| 385 | + regex.push( $.escapeRE( ts.monthNames[0][i] ) ); |
| 386 | + regex.push( $.escapeRE( ts.monthNames[1][i] ) ); |
| 387 | + } |
406 | 388 | |
407 | | - // We allow a trailing percent sign, which we just strip. This works fine |
408 | | - // if percents and regular numbers aren't being mixed. |
409 | | - ts.numberRegex = new RegExp("^(" + "[-+\u2212]?[0-9][0-9,]*(\\.[0-9,]*)?(E[-+\u2212]?[0-9][0-9,]*)?" + // Fortran-style scientific |
410 | | - "|" + "[-+\u2212]?" + digitClass + "+[\\s\\xa0]*%?" + // Generic localised |
411 | | - ")$", "i"); |
412 | | - } |
| 389 | + // Build piped string |
| 390 | + regex = regex.join( '|' ); |
413 | 391 | |
414 | | - function buildDateTable() { |
415 | | - var r = ''; |
416 | | - ts.monthNames = [ |
417 | | - [], |
418 | | - [] |
419 | | - ]; |
420 | | - ts.dateRegex = []; |
| 392 | + // Build RegEx |
| 393 | + // Any date formated with . , ' - or / |
| 394 | + ts.dateRegex[0] = new RegExp( /^\s*\d{1,2}[\,\.\-\/'\s]{1,2}\d{1,2}[\,\.\-\/'\s]{1,2}\d{2,4}\s*?/i); |
421 | 395 | |
422 | | - for ( var i = 1; i < 13; i++ ) { |
423 | | - ts.monthNames[0][i] = mw.config.get( 'wgMonthNames' )[i].toLowerCase(); |
424 | | - ts.monthNames[1][i] = mw.config.get( 'wgMonthNamesShort' )[i].toLowerCase().replace( '.', '' ); |
425 | | - r += $.escapeRE( ts.monthNames[0][i] ) + '|'; |
426 | | - r += $.escapeRE( ts.monthNames[1][i] ) + '|'; |
427 | | - } |
| 396 | + // Written Month name, dmy |
| 397 | + ts.dateRegex[1] = new RegExp( '^\\s*\\d{1,2}[\\,\\.\\-\\/\'\\s]*(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]*\\d{2,4}\\s*$', 'i' ); |
428 | 398 | |
429 | | - //Remove trailing pipe |
430 | | - r = r.slice( 0, -1 ); |
| 399 | + // Written Month name, mdy |
| 400 | + ts.dateRegex[2] = new RegExp( '^\\s*(' + regex + ')' + '[\\,\\.\\-\\/\'\\s]*\\d{1,2}[\\,\\.\\-\\/\'\\s]*\\d{2,4}\\s*$', 'i' ); |
431 | 401 | |
432 | | - //Build RegEx |
433 | | - //Any date formated with . , ' - or / |
434 | | - ts.dateRegex[0] = new RegExp(/^\s*\d{1,2}[\,\.\-\/'\s]{1,2}\d{1,2}[\,\.\-\/'\s]{1,2}\d{2,4}\s*?/i); |
| 402 | + } |
435 | 403 | |
436 | | - //Written Month name, dmy |
437 | | - ts.dateRegex[1] = new RegExp('^\\s*\\d{1,2}[\\,\\.\\-\\/\'\\s]*(' + r + ')' + '[\\,\\.\\-\\/\'\\s]*\\d{2,4}\\s*$', 'i'); |
| 404 | + function explodeRowspans( $table ) { |
| 405 | + // Split multi row cells into multiple cells with the same content |
| 406 | + $table.find( '[rowspan]' ).each(function() { |
| 407 | + var rowSpan = this.rowSpan; |
| 408 | + this.rowSpan = 1; |
| 409 | + var cell = $( this ); |
| 410 | + var next = cell.parent().nextAll(); |
| 411 | + for ( var i = 0; i < rowSpan - 1; i++ ) { |
| 412 | + var td = next.eq( i ).find( 'td' ); |
| 413 | + if ( !td.length ) { |
| 414 | + next.eq( i ).append( cell.clone() ); |
| 415 | + } else if ( this.cellIndex === 0 ) { |
| 416 | + td.eq( this.cellIndex ).before( cell.clone() ); |
| 417 | + } else { |
| 418 | + td.eq( this.cellIndex - 1 ).after( cell.clone() ); |
| 419 | + } |
| 420 | + } |
| 421 | + }); |
| 422 | + } |
438 | 423 | |
439 | | - //Written Month name, mdy |
440 | | - ts.dateRegex[2] = new RegExp('^\\s*(' + r + ')' + '[\\,\\.\\-\\/\'\\s]*\\d{1,2}[\\,\\.\\-\\/\'\\s]*\\d{2,4}\\s*$', 'i'); |
| 424 | + function buildCollationTable() { |
| 425 | + ts.collationTable = mw.config.get( 'tableSorterCollation' ); |
| 426 | + ts.collationRegex = null; |
| 427 | + if ( ts.collationTable ) { |
| 428 | + var keys = []; |
441 | 429 | |
| 430 | + // Build array of key names |
| 431 | + for ( var key in ts.collationTable ) { |
| 432 | + if ( ts.collationTable.hasOwnProperty(key) ) { //to be safe |
| 433 | + keys.push(key); |
| 434 | + } |
442 | 435 | } |
443 | | - |
444 | | - function explodeRowspans( $table ) { |
445 | | - // Split multi row cells into multiple cells with the same content |
446 | | - $table.find( '[rowspan]' ).each(function() { |
447 | | - var rowSpan = this.rowSpan; |
448 | | - this.rowSpan = 1; |
449 | | - var cell = $( this ); |
450 | | - var next = cell.parent().nextAll(); |
451 | | - for ( var i = 0; i < rowSpan - 1; i++ ) { |
452 | | - var td = next.eq( i ).find( 'td' ); |
453 | | - if ( !td.length ) { |
454 | | - next.eq( i ).append( cell.clone() ); |
455 | | - } else if ( this.cellIndex == 0 ) { |
456 | | - td.eq( this.cellIndex ).before( cell.clone() ); |
457 | | - } else { |
458 | | - td.eq( this.cellIndex - 1 ).after( cell.clone() ); |
459 | | - } |
460 | | - } |
461 | | - }); |
| 436 | + if (keys.length) { |
| 437 | + ts.collationRegex = new RegExp( '[' + keys.join( '' ) + ']', 'ig' ); |
462 | 438 | } |
| 439 | + } |
| 440 | + } |
463 | 441 | |
464 | | - function buildCollationTable() { |
465 | | - ts.collationTable = mw.config.get('tableSorterCollation'); |
466 | | - ts.collationRegex = null; |
467 | | - if ( ts.collationTable ) { |
468 | | - var keys = []; |
| 442 | + function cacheRegexs() { |
| 443 | + if ( ts.rgx ) { |
| 444 | + return; |
| 445 | + } |
| 446 | + ts.rgx = { |
| 447 | + IPAddress: [ |
| 448 | + new RegExp( /^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/) |
| 449 | + ], |
| 450 | + currency: [ |
| 451 | + new RegExp( /^[£$€?.]/), |
| 452 | + new RegExp( /[£$€]/g) |
| 453 | + ], |
| 454 | + url: [ |
| 455 | + new RegExp( /^(https?|ftp|file):\/\/$/), |
| 456 | + new RegExp( /(https?|ftp|file):\/\//) |
| 457 | + ], |
| 458 | + isoDate: [ |
| 459 | + new RegExp( /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/) |
| 460 | + ], |
| 461 | + usLongDate: [ |
| 462 | + new RegExp( /^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/) |
| 463 | + ], |
| 464 | + time: [ |
| 465 | + new RegExp( /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/) |
| 466 | + ] |
| 467 | + }; |
| 468 | + } |
469 | 469 | |
470 | | - //Build array of key names |
471 | | - for ( var key in ts.collationTable ) { |
472 | | - if ( ts.collationTable.hasOwnProperty(key) ) { //to be safe |
473 | | - keys.push(key); |
474 | | - } |
| 470 | + /* Public scope */ |
| 471 | + |
| 472 | + $.tablesorter = { |
| 473 | + |
| 474 | + defaultOptions: { |
| 475 | + cssHeader: 'headerSort', |
| 476 | + cssAsc: 'headerSortUp', |
| 477 | + cssDesc: 'headerSortDown', |
| 478 | + cssChildRow: 'expand-child', |
| 479 | + sortInitialOrder: 'asc', |
| 480 | + sortMultiSortKey: 'shiftKey', |
| 481 | + sortLocaleCompare: false, |
| 482 | + parsers: {}, |
| 483 | + widgets: [], |
| 484 | + headers: {}, |
| 485 | + cancelSelection: true, |
| 486 | + sortList: [], |
| 487 | + headerList: [], |
| 488 | + selectorHeaders: 'thead tr:eq(0) th', |
| 489 | + debug: false |
| 490 | + }, |
| 491 | + |
| 492 | + dateRegex: [], |
| 493 | + monthNames: [], |
| 494 | + |
| 495 | + /** |
| 496 | + * @param $tables {jQuery} |
| 497 | + * @param settings {Object} (optional) |
| 498 | + */ |
| 499 | + construct: function( $tables, settings ) { |
| 500 | + return $tables.each( function( i, table ) { |
| 501 | + |
| 502 | + // Quit if no thead or tbody. |
| 503 | + if ( !table.tHead || !table.tBodies ) { |
| 504 | + return; |
475 | 505 | } |
476 | | - if (keys.length) { |
477 | | - ts.collationRegex = new RegExp( '[' + keys.join('') + ']', 'ig' ); |
478 | | - } |
479 | | - } |
480 | | - } |
| 506 | + // Declare and cache. |
| 507 | + var $document, $headers, cache, config, sortOrder, |
| 508 | + $table = $( table ), |
| 509 | + shiftDown = 0, |
| 510 | + firstTime = true; |
481 | 511 | |
482 | | - function cacheRegexs() { |
483 | | - ts.rgx = { |
484 | | - IPAddress: [new RegExp(/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/)], |
485 | | - currency: [new RegExp(/^[£$€?.]/), new RegExp(/[£$€]/g)], |
486 | | - url: [new RegExp(/^(https?|ftp|file):\/\/$/), new RegExp(/(https?|ftp|file):\/\//)], |
487 | | - isoDate: [new RegExp(/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/)], |
488 | | - usLongDate: [new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/)], |
489 | | - time: [new RegExp(/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/)] |
490 | | - }; |
491 | | - } /* public methods */ |
492 | | - this.construct = function ( settings ) { |
493 | | - return this.each( function () { |
494 | | - // if no thead or tbody quit. |
495 | | - if ( !this.tHead || !this.tBodies ) return; |
496 | | - // declare |
497 | | - var $this, $document, $headers, cache, config, shiftDown = 0, |
498 | | - sortOrder, firstTime = true, that = this; |
499 | | - // new blank config object |
500 | | - this.config = {}; |
501 | | - // merge and extend. |
502 | | - config = $.extend( this.config, $.tablesorter.defaults, settings ); |
| 512 | + // New config object. |
| 513 | + table.config = {}; |
503 | 514 | |
504 | | - // store common expression for speed |
505 | | - $this = $( this ); |
506 | | - // save the settings where they read |
507 | | - $.data( this, "tablesorter", config ); |
| 515 | + // Merge and extend. |
| 516 | + config = $.extend( table.config, $.tablesorter.defaultOptions, settings ); |
508 | 517 | |
509 | | - // get the css class names, could be done else where. |
| 518 | + // Save the settings where they read |
| 519 | + $.data( table, 'tablesorter', config ); |
| 520 | + |
| 521 | + // Get the CSS class names, could be done else where. |
510 | 522 | var sortCSS = [ config.cssDesc, config.cssAsc ]; |
511 | 523 | var sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ]; |
512 | 524 | |
513 | | - // build headers |
514 | | - $headers = buildHeaders( this, sortMsg ); |
| 525 | + // Build headers |
| 526 | + $headers = buildHeaders( table, sortMsg ); |
| 527 | + |
515 | 528 | // Grab and process locale settings |
516 | 529 | buildTransformTable(); |
517 | 530 | buildDateTable(); |
518 | 531 | buildCollationTable(); |
519 | 532 | |
520 | | - //Precaching regexps can bring 10 fold |
521 | | - //performance improvements in some browsers |
| 533 | + // Precaching regexps can bring 10 fold |
| 534 | + // performance improvements in some browsers. |
522 | 535 | cacheRegexs(); |
523 | 536 | |
524 | | - // apply event handling to headers |
| 537 | + // Apply event handling to headers |
525 | 538 | // this is to big, perhaps break it out? |
526 | | - $headers.click( |
| 539 | + $headers.click( function( e ) { |
527 | 540 | |
528 | | - function (e) { |
529 | | - //var clickTime= new Date(); |
530 | | - if (firstTime) { |
| 541 | + if ( firstTime ) { |
531 | 542 | firstTime = false; |
532 | | - explodeRowspans( $this ); |
| 543 | + explodeRowspans( $table ); |
533 | 544 | // try to auto detect column type, and store in tables config |
534 | | - that.config.parsers = buildParserCache( that, $headers ); |
| 545 | + table.config.parsers = buildParserCache( table, $headers ); |
535 | 546 | // build the cache for the tbody cells |
536 | | - cache = buildCache( that ); |
| 547 | + cache = buildCache( table ); |
537 | 548 | } |
538 | | - var totalRows = ( $this[0].tBodies[0] && $this[0].tBodies[0].rows.length ) || 0; |
539 | | - if ( !this.sortDisabled && totalRows > 0 ) { |
540 | | - // Only call sortStart if sorting is |
541 | | - // enabled. |
542 | | - //$this.trigger( "sortStart" ); |
| 549 | + var totalRows = ( $table[0].tBodies[0] && $table[0].tBodies[0].rows.length ) || 0; |
| 550 | + if ( !table.sortDisabled && totalRows > 0 ) { |
543 | 551 | |
544 | | - // store exp, for speed |
| 552 | + // Cache jQuery object |
545 | 553 | var $cell = $( this ); |
546 | | - // get current column index |
| 554 | + |
| 555 | + // Get current column index |
547 | 556 | var i = this.column; |
548 | | - // get current column sort order |
| 557 | + |
| 558 | + // Get current column sort order |
549 | 559 | this.order = this.count % 2; |
550 | 560 | this.count++; |
551 | | - // user only whants to sort on one |
552 | | - // column |
| 561 | + |
| 562 | + // User only wants to sort on one column |
553 | 563 | if ( !e[config.sortMultiSortKey] ) { |
554 | | - // flush the sort list |
| 564 | + // Flush the sort list |
555 | 565 | config.sortList = []; |
556 | | - // add column to sort list |
| 566 | + // Add column to sort list |
557 | 567 | config.sortList.push( [i, this.order] ); |
558 | | - // multi column sorting |
| 568 | + |
| 569 | + // Multi column sorting |
559 | 570 | } else { |
560 | | - // the user has clicked on an already sorted column. |
| 571 | + // The user has clicked on an already sorted column. |
561 | 572 | if ( isValueInArray( i, config.sortList ) ) { |
562 | | - // revers the sorting direction |
563 | | - // for all tables. |
| 573 | + // Reverse the sorting direction for all tables. |
564 | 574 | for ( var j = 0; j < config.sortList.length; j++ ) { |
565 | 575 | var s = config.sortList[j], |
566 | 576 | o = config.headerList[s[0]]; |
— | — | @@ -570,79 +580,50 @@ |
571 | 581 | } |
572 | 582 | } |
573 | 583 | } else { |
574 | | - // add column to sort list array |
| 584 | + // Add column to sort list array |
575 | 585 | config.sortList.push( [i, this.order] ); |
576 | 586 | } |
577 | 587 | } |
578 | 588 | |
579 | | - // set css for headers |
580 | | - setHeadersCss( $this[0], $headers, config.sortList, sortCSS, sortMsg ); |
581 | | - appendToTable( |
582 | | - $this[0], multisort( |
583 | | - $this[0], config.sortList, cache ) ); |
584 | | - //benchmark( "Sorting " + totalRows + " rows:", clickTime ); |
| 589 | + // Set CSS for headers |
| 590 | + setHeadersCss( $table[0], $headers, config.sortList, sortCSS, sortMsg ); |
| 591 | + appendToTable( |
| 592 | + $table[0], multisort( $table[0], config.sortList, cache ) |
| 593 | + ); |
585 | 594 | |
586 | | - // stop normal event by returning false |
| 595 | + // Stop normal event by returning false |
587 | 596 | return false; |
588 | 597 | } |
589 | | - // cancel selection |
590 | | - } ).mousedown( function () { |
| 598 | + |
| 599 | + // Cancel selection |
| 600 | + } ).mousedown( function() { |
591 | 601 | if ( config.cancelSelection ) { |
592 | | - this.onselectstart = function () { |
| 602 | + this.onselectstart = function() { |
593 | 603 | return false; |
594 | 604 | }; |
595 | 605 | return false; |
596 | 606 | } |
597 | 607 | } ); |
598 | | - // apply easy methods that trigger binded events |
599 | | - //Can't think of any use for these in a mw context |
600 | | - // $this.bind( "update", function () { |
601 | | - // var me = this; |
602 | | - // setTimeout( function () { |
603 | | - // // rebuild parsers. |
604 | | - // me.config.parsers = buildParserCache( |
605 | | - // me, $headers ); |
606 | | - // // rebuild the cache map |
607 | | - // cache = buildCache(me); |
608 | | - // }, 1 ); |
609 | | - // } ).bind( "updateCell", function ( e, cell ) { |
610 | | - // var config = this.config; |
611 | | - // // get position from the dom. |
612 | | - // var pos = [( cell.parentNode.rowIndex - 1 ), cell.cellIndex]; |
613 | | - // // update cache |
614 | | - // cache.normalized[pos[0]][pos[1]] = config.parsers[pos[1]].format( |
615 | | - // getElementText( cell ), cell ); |
616 | | - // } ).bind( "sorton", function ( e, list ) { |
617 | | - // $( this ).trigger( "sortStart" ); |
618 | | - // config.sortList = list; |
619 | | - // // update and store the sortlist |
620 | | - // var sortList = config.sortList; |
621 | | - // // update header count index |
622 | | - // updateHeaderSortCount( this, sortList ); |
623 | | - // // set css for headers |
624 | | - // setHeadersCss( this, $headers, sortList, sortCSS ); |
625 | | - // // sort the table and append it to the dom |
626 | | - // appendToTable( this, multisort( this, sortList, cache ) ); |
627 | | - // } ).bind( "appendCache", function () { |
628 | | - // appendToTable( this, cache ); |
629 | | - // } ); |
| 608 | + |
630 | 609 | } ); |
631 | | - }; |
632 | | - this.addParser = function ( parser ) { |
633 | | - var l = parsers.length, |
| 610 | + }, |
| 611 | + |
| 612 | + addParser: function( parser ) { |
| 613 | + var l = parsers.length, |
634 | 614 | a = true; |
635 | 615 | for ( var i = 0; i < l; i++ ) { |
636 | 616 | if ( parsers[i].id.toLowerCase() == parser.id.toLowerCase() ) { |
637 | 617 | a = false; |
638 | 618 | } |
639 | 619 | } |
640 | | - if (a) { |
| 620 | + if ( a ) { |
641 | 621 | parsers.push( parser ); |
642 | 622 | } |
643 | | - }; |
644 | | - this.formatDigit = function (s) { |
645 | | - if ( ts.transformTable != false ) { |
646 | | - var out = '', |
| 623 | + }, |
| 624 | + |
| 625 | + formatDigit: function( s ) { |
| 626 | + if ( ts.transformTable !== false ) { |
| 627 | + var out = '', |
647 | 628 | c; |
648 | 629 | for ( var p = 0; p < s.length; p++ ) { |
649 | 630 | c = s.charAt(p); |
— | — | @@ -654,134 +635,137 @@ |
655 | 636 | } |
656 | 637 | s = out; |
657 | 638 | } |
658 | | - var i = parseFloat( s.replace(/[, ]/g, '').replace( "\u2212", '-' ) ); |
| 639 | + var i = parseFloat( s.replace( /[, ]/g, '' ).replace( "\u2212", '-' ) ); |
659 | 640 | return ( isNaN(i)) ? 0 : i; |
660 | | - }; |
661 | | - this.formatFloat = function (s) { |
| 641 | + }, |
| 642 | + |
| 643 | + formatFloat: function( s ) { |
662 | 644 | var i = parseFloat(s); |
663 | 645 | return ( isNaN(i)) ? 0 : i; |
664 | | - }; |
665 | | - this.formatInt = function (s) { |
| 646 | + }, |
| 647 | + |
| 648 | + formatInt: function( s ) { |
666 | 649 | var i = parseInt( s, 10 ); |
667 | 650 | return ( isNaN(i)) ? 0 : i; |
668 | | - }; |
669 | | - this.clearTableBody = function ( table ) { |
| 651 | + }, |
| 652 | + |
| 653 | + clearTableBody: function( table ) { |
670 | 654 | if ( $.browser.msie ) { |
671 | | - function empty() { |
672 | | - while ( this.firstChild ) |
673 | | - this.removeChild( this.firstChild ); |
674 | | - } |
675 | | - empty.apply( table.tBodies[0] ); |
| 655 | + var empty = function( el ) { |
| 656 | + while ( el.firstChild ) { |
| 657 | + el.removeChild( el.firstChild ); |
| 658 | + } |
| 659 | + }; |
| 660 | + empty( table.tBodies[0] ); |
676 | 661 | } else { |
677 | | - table.tBodies[0].innerHTML = ""; |
| 662 | + table.tBodies[0].innerHTML = ''; |
678 | 663 | } |
679 | | - }; |
680 | | - } |
681 | | - } ); |
| 664 | + } |
| 665 | + }; |
682 | 666 | |
683 | | - // extend plugin scope |
684 | | - $.fn.extend( { |
685 | | - tablesorter: $.tablesorter.construct |
686 | | - } ); |
| 667 | + // Shortcut |
| 668 | + ts = $.tablesorter; |
687 | 669 | |
688 | | - // make shortcut |
689 | | - var ts = $.tablesorter; |
| 670 | + // Register as jQuery prototype method |
| 671 | + $.fn.tablesorter = function( settings ) { |
| 672 | + return ts.construct( this, settings ); |
| 673 | + }; |
690 | 674 | |
691 | | - // add default parsers |
| 675 | + // Add default parsers |
692 | 676 | ts.addParser( { |
693 | | - id: "text", |
694 | | - is: function (s) { |
| 677 | + id: 'text', |
| 678 | + is: function( s ) { |
695 | 679 | return true; |
696 | 680 | }, |
697 | | - format: function (s) { |
| 681 | + format: function( s ) { |
698 | 682 | s = $.trim( s.toLowerCase() ); |
699 | 683 | if ( ts.collationRegex ) { |
700 | 684 | var tsc = ts.collationTable; |
701 | | - s = s.replace( ts.collationRegex, function ( match ) { |
| 685 | + s = s.replace( ts.collationRegex, function( match ) { |
702 | 686 | var r = tsc[match] ? tsc[match] : tsc[match.toUpperCase()]; |
703 | 687 | return r.toLowerCase(); |
704 | 688 | } ); |
705 | 689 | } |
706 | 690 | return s; |
707 | 691 | }, |
708 | | - type: "text" |
| 692 | + type: 'text' |
709 | 693 | } ); |
710 | 694 | |
711 | 695 | ts.addParser( { |
712 | | - id: "IPAddress", |
713 | | - is: function (s) { |
| 696 | + id: 'IPAddress', |
| 697 | + is: function( s ) { |
714 | 698 | return ts.rgx.IPAddress[0].test(s); |
715 | 699 | }, |
716 | | - format: function (s) { |
717 | | - var a = s.split("."), |
718 | | - r = "", |
| 700 | + format: function( s ) { |
| 701 | + var a = s.split( '.' ), |
| 702 | + r = '', |
719 | 703 | l = a.length; |
720 | 704 | for ( var i = 0; i < l; i++ ) { |
721 | 705 | var item = a[i]; |
722 | 706 | if ( item.length == 1 ) { |
723 | | - r += "00" + item; |
| 707 | + r += '00' + item; |
724 | 708 | } else if ( item.length == 2 ) { |
725 | | - r += "0" + item; |
| 709 | + r += '0' + item; |
726 | 710 | } else { |
727 | 711 | r += item; |
728 | 712 | } |
729 | 713 | } |
730 | 714 | return $.tablesorter.formatFloat(r); |
731 | 715 | }, |
732 | | - type: "numeric" |
| 716 | + type: 'numeric' |
733 | 717 | } ); |
734 | 718 | |
735 | 719 | ts.addParser( { |
736 | | - id: "currency", |
737 | | - is: function (s) { |
| 720 | + id: 'currency', |
| 721 | + is: function( s ) { |
738 | 722 | return ts.rgx.currency[0].test(s); |
739 | 723 | }, |
740 | | - format: function (s) { |
741 | | - return $.tablesorter.formatDigit( s.replace( ts.rgx.currency[1], "" ) ); |
| 724 | + format: function( s ) { |
| 725 | + return $.tablesorter.formatDigit( s.replace( ts.rgx.currency[1], '' ) ); |
742 | 726 | }, |
743 | | - type: "numeric" |
| 727 | + type: 'numeric' |
744 | 728 | } ); |
745 | 729 | |
746 | 730 | ts.addParser( { |
747 | | - id: "url", |
748 | | - is: function (s) { |
| 731 | + id: 'url', |
| 732 | + is: function( s ) { |
749 | 733 | return ts.rgx.url[0].test(s); |
750 | 734 | }, |
751 | | - format: function (s) { |
| 735 | + format: function( s ) { |
752 | 736 | return $.trim( s.replace( ts.rgx.url[1], '' ) ); |
753 | 737 | }, |
754 | | - type: "text" |
| 738 | + type: 'text' |
755 | 739 | } ); |
756 | 740 | |
757 | 741 | ts.addParser( { |
758 | | - id: "isoDate", |
759 | | - is: function (s) { |
| 742 | + id: 'isoDate', |
| 743 | + is: function( s ) { |
760 | 744 | return ts.rgx.isoDate[0].test(s); |
761 | 745 | }, |
762 | | - format: function (s) { |
763 | | - return $.tablesorter.formatFloat((s != "") ? new Date(s.replace( |
764 | | - new RegExp(/-/g), "/")).getTime() : "0"); |
| 746 | + format: function( s ) { |
| 747 | + return $.tablesorter.formatFloat((s !== '') ? new Date(s.replace( |
| 748 | + new RegExp( /-/g), '/')).getTime() : '0' ); |
765 | 749 | }, |
766 | | - type: "numeric" |
| 750 | + type: 'numeric' |
767 | 751 | } ); |
768 | 752 | |
769 | 753 | ts.addParser( { |
770 | | - id: "usLongDate", |
771 | | - is: function (s) { |
| 754 | + id: 'usLongDate', |
| 755 | + is: function( s ) { |
772 | 756 | return ts.rgx.usLongDate[0].test(s); |
773 | 757 | }, |
774 | | - format: function (s) { |
| 758 | + format: function( s ) { |
775 | 759 | return $.tablesorter.formatFloat( new Date(s).getTime() ); |
776 | 760 | }, |
777 | | - type: "numeric" |
| 761 | + type: 'numeric' |
778 | 762 | } ); |
779 | 763 | |
780 | 764 | ts.addParser( { |
781 | | - id: "date", |
782 | | - is: function (s) { |
| 765 | + id: 'date', |
| 766 | + is: function( s ) { |
783 | 767 | return ( ts.dateRegex[0].test(s) || ts.dateRegex[1].test(s) || ts.dateRegex[2].test(s )); |
784 | 768 | }, |
785 | | - format: function ( s, table ) { |
| 769 | + format: function( s, table ) { |
786 | 770 | s = $.trim( s.toLowerCase() ); |
787 | 771 | |
788 | 772 | for ( var i = 1, j = 0; i < 13 && j < 2; i++ ) { |
— | — | @@ -792,61 +776,67 @@ |
793 | 777 | } |
794 | 778 | } |
795 | 779 | |
796 | | - s = s.replace(/[\-\.\,' ]/g, "/"); |
| 780 | + s = s.replace( /[\-\.\,' ]/g, '/' ); |
797 | 781 | |
798 | | - //Replace double slashes |
799 | | - s = s.replace(/\/\//g, "/"); |
800 | | - s = s.replace(/\/\//g, "/"); |
801 | | - s = s.split('/'); |
| 782 | + // Replace double slashes |
| 783 | + s = s.replace( /\/\//g, '/' ); |
| 784 | + s = s.replace( /\/\//g, '/' ); |
| 785 | + s = s.split( '/' ); |
802 | 786 | |
803 | | - //Pad Month and Day |
804 | | - if ( s[0] && s[0].length == 1 ) s[0] = "0" + s[0]; |
805 | | - if ( s[1] && s[1].length == 1 ) s[1] = "0" + s[1]; |
| 787 | + // Pad Month and Day |
| 788 | + if ( s[0] && s[0].length == 1 ) { |
| 789 | + s[0] = '0' + s[0]; |
| 790 | + } |
| 791 | + if ( s[1] && s[1].length == 1 ) { |
| 792 | + s[1] = '0' + s[1]; |
| 793 | + } |
806 | 794 | var y; |
807 | 795 | |
808 | 796 | if ( !s[2] ) { |
809 | | - //Fix yearless dates |
| 797 | + // Fix yearless dates |
810 | 798 | s[2] = 2000; |
811 | 799 | } else if ( ( y = parseInt( s[2], 10) ) < 100 ) { |
812 | | - //Guestimate years without centuries |
| 800 | + // Guestimate years without centuries |
813 | 801 | if ( y < 30 ) { |
814 | 802 | s[2] = 2000 + y; |
815 | 803 | } else { |
816 | 804 | s[2] = 1900 + y; |
817 | 805 | } |
818 | 806 | } |
819 | | - //Resort array depending on preferences |
820 | | - if ( mw.config.get( 'wgDefaultDateFormat' ) == "mdy" || mw.config.get('wgContentLanguage') == 'en' ) { |
| 807 | + // Resort array depending on preferences |
| 808 | + if ( mw.config.get( 'wgDefaultDateFormat' ) == 'mdy' || mw.config.get( 'wgContentLanguage' ) == 'en' ) { |
821 | 809 | s.push( s.shift() ); |
822 | 810 | s.push( s.shift() ); |
823 | | - } else if ( mw.config.get( 'wgDefaultDateFormat' ) == "dmy" ) { |
| 811 | + } else if ( mw.config.get( 'wgDefaultDateFormat' ) == 'dmy' ) { |
824 | 812 | var d = s.shift(); |
825 | 813 | s.push( s.shift() ); |
826 | 814 | s.push(d); |
827 | 815 | } |
828 | | - return parseInt( s.join(''), 10 ); |
| 816 | + return parseInt( s.join( '' ), 10 ); |
829 | 817 | }, |
830 | | - type: "numeric" |
| 818 | + type: 'numeric' |
831 | 819 | } ); |
| 820 | + |
832 | 821 | ts.addParser( { |
833 | | - id: "time", |
834 | | - is: function (s) { |
| 822 | + id: 'time', |
| 823 | + is: function( s ) { |
835 | 824 | return ts.rgx.time[0].test(s); |
836 | 825 | }, |
837 | | - format: function (s) { |
838 | | - return $.tablesorter.formatFloat( new Date( "2000/01/01 " + s ).getTime() ); |
| 826 | + format: function( s ) { |
| 827 | + return $.tablesorter.formatFloat( new Date( '2000/01/01 ' + s ).getTime() ); |
839 | 828 | }, |
840 | | - type: "numeric" |
| 829 | + type: 'numeric' |
841 | 830 | } ); |
| 831 | + |
842 | 832 | ts.addParser( { |
843 | | - id: "number", |
844 | | - is: function ( s, table ) { |
845 | | - return $.tablesorter.numberRegex.test( $.trim(s )); |
| 833 | + id: 'number', |
| 834 | + is: function( s, table ) { |
| 835 | + return $.tablesorter.numberRegex.test( $.trim( s )); |
846 | 836 | }, |
847 | | - format: function (s) { |
| 837 | + format: function( s ) { |
848 | 838 | return $.tablesorter.formatDigit(s); |
849 | 839 | }, |
850 | | - type: "numeric" |
| 840 | + type: 'numeric' |
851 | 841 | } ); |
852 | | - |
| 842 | + |
853 | 843 | } )( jQuery ); |