5bd18718ec9fc368755e003799e61045447483ad
[atutor.git] / mods / photo_album / fluid / component-templates / js / jquery.ui-1.0 / ui.tablesorter.js
1 /*\r
2  * \r
3  * TableSorter 2.0 - Client-side table sorting with ease!\r
4  * Version 2.0\r
5  * @requires jQuery v1.1.3\r
6  * \r
7  * Copyright (c) 2007 Christian Bach\r
8  * Examples and docs at: http://tablesorter.com\r
9  * Dual licensed under the MIT and GPL licenses:\r
10  * http://www.opensource.org/licenses/mit-license.php\r
11  * http://www.gnu.org/licenses/gpl.html\r
12  * \r
13  */\r
14 /**\r
15  *\r
16  * @description Create a sortable table with multi-column sorting capabilitys\r
17  * \r
18  * @example $('#table').tablesorter();\r
19  * @desc Create a simple tablesorter interface.\r
20  *\r
21  * @example $('#table').tablesorter({ sortList:[[0,0],[1,0]] });\r
22  * @desc Create a tablesorter interface and sort on the first and secound column in ascending order.\r
23  * \r
24  * @example $('#table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } });\r
25  * @desc Create a tablesorter interface and disableing the first and secound column headers.\r
26  * \r
27  * @example $('#table').tablesorter({ 0: {sorter:"integer"}, 1: {sorter:"currency"} });\r
28  * @desc Create a tablesorter interface and set a column parser for the first and secound column.\r
29  * \r
30  * \r
31  * @param Object settings An object literal containing key/value pairs to provide optional settings.\r
32  * \r
33  * @option String cssHeader (optional)                  A string of the class name to be appended to sortable tr elements in the thead of the table. \r
34  *                                                                                              Default value: "header"\r
35  * \r
36  * @option String cssAsc (optional)                     A string of the class name to be appended to sortable tr elements in the thead on a ascending sort. \r
37  *                                                                                              Default value: "headerSortUp"\r
38  * \r
39  * @option String cssDesc (optional)                    A string of the class name to be appended to sortable tr elements in the thead on a descending sort. \r
40  *                                                                                              Default value: "headerSortDown"\r
41  * \r
42  * @option String sortInitialOrder (optional)   A string of the inital sorting order can be asc or desc. \r
43  *                                                                                              Default value: "asc"\r
44  * \r
45  * @option String sortMultisortKey (optional)   A string of the multi-column sort key. \r
46  *                                                                                              Default value: "shiftKey"\r
47  * \r
48  * @option String textExtraction (optional)     A string of the text-extraction method to use. \r
49  *                                                                                              For complex html structures inside td cell set this option to "complex", \r
50  *                                                                                              on large tables the complex option can be slow. \r
51  *                                                                                              Default value: "simple"\r
52  * \r
53  * @option Object headers (optional)                    An array containing the forces sorting rules. \r
54  *                                                                                              This option let's you specify a default sorting rule. \r
55  *                                                                                              Default value: null\r
56  * \r
57  * @option Array sortList (optional)                    An array containing the forces sorting rules. \r
58  *                                                                                              This option let's you specify a default sorting rule. \r
59  *                                                                                              Default value: null\r
60  * \r
61  * @option Array sortForce (optional)                   An array containing the forces sorting rules. \r
62  *                                                                                              This option let's you specify a default sorting rule. \r
63  *                                                                                              Default value: null\r
64  *  \r
65  * \r
66  * @option Boolean widthFixed (optional)                Boolean flag indicating if tablesorter should apply fixed widths to the table columns.\r
67  *                                                                                              This is usefull when using the pager companion plugin.\r
68  *                                                                                              This options requires the dimension jquery plugin.\r
69  *                                                                                              Default value: false\r
70  *\r
71  * @option Boolean cancelSelection (optional)   Boolean flag indicating if tablesorter should cancel selection of the table headers text.\r
72  *                                                                                              Default value: true\r
73  * \r
74  * @type jQuery\r
75  *\r
76  * @name tablesorter\r
77  * \r
78  * @cat Plugins/Tablesorter\r
79  * \r
80  * @author Christian Bach/christian.bach@polyester.se\r
81  */\r
82 \r
83 (function($) {\r
84         $.extend({\r
85                 tablesorter: new function() {\r
86                         \r
87                         var parsers = [], widgets = [];\r
88                         \r
89                         this.defaults = {\r
90                                 cssHeader: "header",\r
91                                 cssAsc: "headerSortUp",\r
92                                 cssDesc: "headerSortDown",\r
93                                 sortInitialOrder: "asc",\r
94                                 sortMultiSortKey: "shiftKey",\r
95                                 sortForce: null,\r
96                                 textExtraction: "simple",\r
97                                 parsers: {}, \r
98                                 widgets: [],            \r
99                                 widgetZebra: {css: ["even","odd"]},\r
100                                 headers: {},\r
101                                 widthFixed: false,\r
102                                 cancelSelection: true,\r
103                                 sortList: [],\r
104                                 headerList: [],\r
105                                 dateFormat: "us",\r
106                                 debug: false\r
107                         };\r
108                         \r
109                         /* debuging utils */\r
110                         function benchmark(label,stamp) {\r
111                                 log(label + "," + (new Date().getTime() - stamp.getTime()) + "ms");\r
112                         }\r
113                         \r
114                         function log(s) {\r
115                                 if (typeof console != "undefined" && typeof console.debug != "undefined") {\r
116                                         console.log(s);\r
117                                 } else {\r
118                                         alert(s);\r
119                                 }
120                         }\r
121                                                 \r
122                         /* parsers utils */\r
123                         function buildParserCache(table,$headers) {\r
124                                 \r
125                                 if(table.config.debug) { var parsersDebug = ""; }\r
126                                 \r
127                                 var list = [], cells = table.tBodies[0].rows[0].cells, l = cells.length;\r
128                                 \r
129                                 for (var i=0;i < l; i++) {\r
130                                         var p = false;\r
131                                         \r
132                                         if($.meta && ($($headers[i]).data() && $($headers[i]).data().sorter)  ) {\r
133                                         \r
134                                                 p = getParserById($($headers[i]).data().sorter);        \r
135                                         \r
136                                         } else if((table.config.headers[i] && table.config.headers[i].sorter)) {\r
137 \r
138                                                 p = getParserById(table.config.headers[i].sorter);\r
139                                         }\r
140                                         if(!p) {\r
141                                                 p = detectParserForColumn(table.config,cells[i]);\r
142                                         }\r
143 \r
144                                         if(table.config.debug) { parsersDebug += "column:" + i + " parser:" +p.id + "\n"; }\r
145 \r
146                                         list.push(p);\r
147                                 }\r
148 \r
149                                 if(table.config.debug) { log(parsersDebug); }\r
150 \r
151                                 return list;\r
152                         };\r
153                         \r
154                         function detectParserForColumn(config,node) {\r
155                                 var l = parsers.length;\r
156                                 for(var i=1; i < l; i++) {\r
157                                         if(parsers[i].is($.trim(getElementText(config,node)))) {\r
158                                                 return parsers[i];\r
159                                         }\r
160                                 }\r
161                                 \r
162                                 // 0 is always the generic parser (text)\r
163                                 return parsers[0];\r
164                         }\r
165                         \r
166                         function getParserById(name) {\r
167                                 var l = parsers.length;\r
168                                 for(var i=0; i < l; i++) {\r
169                                         if(parsers[i].id.toLowerCase() == name.toLowerCase()) { \r
170                                                 return parsers[i];\r
171                                         }\r
172                                 }\r
173                                 return false;\r
174                         }\r
175                         \r
176                         /* utils */\r
177                         function buildCache(table) {\r
178                                 \r
179                                 if(table.config.debug) { var cacheTime = new Date(); }\r
180                                 \r
181                                 var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0,\r
182                                         totalCells = table.tBodies[0].rows[0].cells.length,\r
183                                         parsers = table.config.parsers, \r
184                                         cache = {row: [], normalized: []};\r
185                                 \r
186                                         for (var i=0;i < totalRows; ++i) {\r
187                                         \r
188                                                 /** Add the table data to main data array */\r
189                                                 var c = table.tBodies[0].rows[i], cols = [];\r
190                                         \r
191                                                 cache.row.push($(c));\r
192                                                 \r
193                                                 for(var j=0; j < totalCells; ++j) {\r
194                                                         cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j])); \r
195                                                 }\r
196                                                                                                 \r
197                                                 cols.push(i); // add position for rowCache\r
198                                                 cache.normalized.push(cols);\r
199                                                 cols = null;\r
200                                         };\r
201                                 \r
202                                 if(table.config.debug) { benchmark("Building cache for " + totalRows + " rows:", cacheTime); }\r
203                                 \r
204                                 return cache;\r
205                         };\r
206                         \r
207                         function getElementText(config,node) {\r
208                                 \r
209                                 if(!node) return "";\r
210                                                                 \r
211                                 var t = "";\r
212                                 \r
213                                 \r
214                                 if(typeof(config.textExtraction) == "function") {\r
215                                         t = config.textExtraction(node);\r
216                                 } else if(config.textExtraction == "complex") { \r
217                                         t = $(node).text();\r
218                                 } else {\r
219                                         if(node.childNodes[0] && node.childNodes[0].hasChildNodes()) {\r
220                                                 t = node.childNodes[0].innerHTML;\r
221                                         } else {\r
222                                                 t = node.innerHTML;\r
223                                         }\r
224                                 }\r
225                                 return t;\r
226                         }\r
227                         \r
228                         function appendToTable(table,cache) {\r
229                                 \r
230                                 if(table.config.debug) {var appendTime = new Date()}\r
231                                 \r
232                                 var c = cache, \r
233                                         r = c.row, \r
234                                         n= c.normalized, \r
235                                         totalRows = n.length, \r
236                                         checkCell = (n[0].length-1), \r
237                                         tableBody = $("tbody:first",table).empty();\r
238                                         rows = [];\r
239                                 \r
240                                 for (var i=0;i < totalRows; i++) {\r
241                                                 rows.push(r[n[i][checkCell]]);\r
242                                                 if(table.config.appender == null) {\r
243                                                         tableBody.append(r[n[i][checkCell]]);\r
244                                                 }\r
245                                 }       \r
246 \r
247                                 if(table.config.appender != null) {\r
248                                         table.config.appender(table,rows);      \r
249                                 }\r
250                                 \r
251                                 rows = null;\r
252                                 \r
253                                 //apply table widgets\r
254                                 applyWidget(table);\r
255                                 \r
256                                 if(table.config.debug) { benchmark("Rebuilt table:", appendTime); }\r
257                         \r
258                         };\r
259                         \r
260                         function buildHeaders(table) {\r
261                                 \r
262                                 if(table.config.debug) { var time = new Date(); }\r
263                                 \r
264                                 var meta = ($.meta) ? true : false, tableHeadersRows = [];\r
265                         \r
266                                 for(var i = 0; i < table.tHead.rows.length; i++) { tableHeadersRows[i]=0; };\r
267                                 \r
268                                 $tableHeaders = $(checkCellColSpan(table, tableHeadersRows, 0,table.tHead.rows[0].cells.length));\r
269                 \r
270                                 $tableHeaders.each(function(index) {\r
271                                                         \r
272                                         this.count = 0;\r
273                                         this.column = index;\r
274                                         this.order = formatSortingOrder(table.config.sortInitialOrder);\r
275                                         \r
276                                         if(checkHeaderMetadata(this) || checkHeaderOptions(table,index)) this.sortDisabled = true;\r
277                                         \r
278                                         if(!this.sortDisabled) {\r
279                                                 $(this).addClass(table.config.cssHeader);\r
280                                         }\r
281                                         \r
282                                         // add cell to headerList\r
283                                         table.config.headerList[index]= this;\r
284                                 });\r
285                                 \r
286                                 if(table.config.debug) { benchmark("Built headers:", time); log($tableHeaders); }\r
287                                 \r
288                                 return $tableHeaders;\r
289                                 
290                         };\r
291                                                 \r
292                         function checkCellColSpan(table, headerArr, row) {\r
293                 var arr = [], r = table.tHead.rows, c = r[row].cells;\r
294                                 \r
295                                 for(var i=headerArr[row]; i < c.length; i++) {\r
296                                         var cell = c[i];\r
297                                         \r
298                                         if ( cell.colSpan > 1) { \r
299                                                 arr = arr.concat(checkCellColSpan(table, headerArr,row+cell.rowSpan));\r
300                                         } else  {\r
301                                                 if(table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row+1])) {\r
302                                                         arr.push(cell);\r
303                                                 }\r
304                                                 headerArr[row] = (i+row);\r
305                                         }\r
306                                 }\r
307                                 return arr;\r
308                         };\r
309                         \r
310                         function checkHeaderMetadata(cell) {\r
311                                 if(($.meta) && ($(cell).data().sorter === false)) { return true; };\r
312                                 return false;\r
313                         }\r
314                         \r
315                         function checkHeaderOptions(table,i) {  \r
316                                 if((table.config.headers[i]) && (table.config.headers[i].sorter === false)) { return true; };\r
317                                 return false;\r
318                         }\r
319                         \r
320                         function applyWidget(table) {\r
321                                 var c = table.config.widgets;\r
322                                 var l = c.length;\r
323                                 for(var i=0; i < l; i++) {\r
324                                         \r
325                                         getWidgetById(c[i]).format(table);\r
326                                 }\r
327                                 \r
328                         }\r
329                         \r
330                         function getWidgetById(name) {\r
331                                 var l = widgets.length;\r
332                                 for(var i=0; i < l; i++) {\r
333                                         if(widgets[i].id.toLowerCase() == name.toLowerCase() ) {\r
334                                                 return widgets[i]; \r
335                                         }\r
336                                 }\r
337                         };\r
338                         \r
339                         function formatSortingOrder(v) {\r
340                                 \r
341                                 if(typeof(v) != "Number") {\r
342                                         i = (v.toLowerCase() == "desc") ? 1 : 0;
343                                 } else {\r
344                                         i = (v == (0 || 1)) ? v : 0;
345                                 }\r
346                                 return i;
347                         }\r
348                         \r
349                         function isValueInArray(v, a) {\r
350                                 var l = a.length;\r
351                                 for(var i=0; i < l; i++) {\r
352                                         if(a[i][0] == v) {\r
353                                                 return true;    
354                                         }
355                                 }\r
356                                 return false;
357                         }\r
358                                 \r
359                         function setHeadersCss(table,$headers, list, css) {\r
360                                 // remove all header information\r
361                                 $headers.removeClass(css[0]).removeClass(css[1]);\r
362                                 \r
363                                 var h = [];\r
364                                 $headers.each(function(offset) {\r
365                                                 if(!this.sortDisabled) {\r
366                                                         h[this.column] = $(this);                                       \r
367                                                 }\r
368                                 });\r
369 \r
370                                 var l = list.length; \r
371                                 for(var i=0; i < l; i++) {\r
372                                         h[list[i][0]].addClass(css[list[i][1]]);\r
373                                 }\r
374                         }\r
375                         \r
376                         function fixColumnWidth(table,$headers) {\r
377                                 var c = table.config;\r
378                                 if(c.widthFixed) {\r
379                                         var colgroup = $('<colgroup>');\r
380                                         $("tbody:first tr:first td",table).each(function() {\r
381                                                 \r
382                                                 colgroup.append($('<col>').css('width',$(this).width()));\r
383                                         \r
384                                         });\r
385                                         $(table).prepend(colgroup);\r
386                                 };\r
387                         }\r
388                         \r
389                         function updateHeaderSortCount(table,sortList) {\r
390                                 var c = table.config, l = sortList.length;\r
391                                 for(var i=0; i < l; i++) {\r
392                                         var s = sortList[i], o = c.headerList[s[0]];\r
393                                         o.count = s[1];\r
394                                         o.count++;\r
395                                 }\r
396                         }\r
397                         \r
398                         /* sorting methods */\r
399                         function multisort(table,sortList,cache) {\r
400                                 \r
401                                 if(table.config.debug) { var sortTime = new Date(); }\r
402                                 \r
403                                 var dynamicExp = "var sortWrapper = function(a,b) {", l = sortList.length;\r
404                                         \r
405                                 for(var i=0; i < l; i++) {\r
406                                         \r
407                                         var c = sortList[i][0];\r
408                                         var order = sortList[i][1];\r
409                                         var s = (getCachedSortType(table.config.parsers,c) == "text") ? ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ? "sortNumeric" : "sortNumericDesc");\r
410                                         \r
411                                         var e = "e" + i;\r
412                                         \r
413                                         dynamicExp += "var " + e + " = " + s + "(a[" + c + "],b[" + c + "]); ";\r
414                                         dynamicExp += "if(" + e + ") { return " + e + "; } ";\r
415                                         dynamicExp += "else { ";\r
416                                 }\r
417                                         \r
418                                 for(var i=0; i < l; i++) {\r
419                                         dynamicExp += "}; ";\r
420                                 }\r
421                                 \r
422                                 dynamicExp += "return 0; ";     \r
423                                 dynamicExp += "}; ";    \r
424                                 \r
425                                 eval(dynamicExp);\r
426                                 \r
427                                 cache.normalized.sort(sortWrapper);\r
428                                 \r
429                                 if(table.config.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order+ " time:", sortTime); }\r
430                                 \r
431                                 return cache;\r
432                         };\r
433                         \r
434                         function sortText(a,b) {\r
435                                 return ((a < b) ? -1 : ((a > b) ? 1 : 0));\r
436                         };\r
437                         \r
438                         function sortTextDesc(a,b) {\r
439                                 return ((b < a) ? -1 : ((b > a) ? 1 : 0));\r
440                         };      \r
441                         \r
442                         function sortNumeric(a,b) {\r
443                                 return a-b;\r
444                         };\r
445                         \r
446                         function sortNumericDesc(a,b) {\r
447                                 return b-a;\r
448                         };\r
449                         \r
450                         function getCachedSortType(parsers,i) {\r
451                                 return parsers[i].type;\r
452                         };\r
453                         \r
454                         /* public methods */\r
455                         this.construct = function(settings) {\r
456 \r
457                                 return this.each(function() {\r
458                                         \r
459                                         \r
460                                         \r
461                                         \r
462                                         var $this, $document,$headers, cache, config, shiftDown = 0, sortOrder;\r
463                                         \r
464                                         this.config = {};\r
465                                         \r
466                                         config = $.extend(this.config, $.tablesorter.defaults, settings);\r
467                                         \r
468                                         if(!this.tHead || !this.tBodies) return true;\r
469                                         \r
470                                         // store common expression for speed                                    \r
471                                         $this = $(this);\r
472                                         \r
473                                         // build headers\r
474                                         $headers = buildHeaders(this);\r
475                                         \r
476                                         // try to auto detect column type, and store in tables config\r
477                                         this.config.parsers = buildParserCache(this,$headers);\r
478                                         \r
479                                         \r
480                                         // build the cache for the tbody cells\r
481                                         cache = buildCache(this);\r
482                                         \r
483                                         // get the css class names, could be done else where.\r
484                                         var sortCSS = [config.cssDesc,config.cssAsc];\r
485                                         \r
486                                         // fixate columns if the users supplies the fixedWidth option\r
487                                         fixColumnWidth(this);\r
488                                         \r
489                                         // apply event handling to headers\r
490                                         // this is to big, perhaps break it out?\r
491                                         $headers.click(function(e) {\r
492                                                 if(!this.sortDisabled) {\r
493                                                         // store exp, for speed\r
494                                                         var $cell = $(this);\r
495         \r
496                                                         // get current column index\r
497                                                         var i = this.column;\r
498                                                         \r
499                                                         // get current column sort order\r
500                                                         this.order = this.count++ % 2;\r
501                                                         \r
502                                                         \r
503                                                         \r
504                                                         // user only whants to sort on one column\r
505                                                         if(!e[config.sortMultiSortKey]) {\r
506                                                                 \r
507                                                                 // flush the sort list\r
508                                                                 config.sortList = [];\r
509                                                                 \r
510                                                                 if(config.sortForce != null) {\r
511                                                                         var a = config.sortForce; \r
512                                                                         for(var j=0; j < a.length; j++) {       \r
513                                                                                 config.sortList.push(a[j]);     \r
514                                                                         }\r
515                                                                 }\r
516                                                                 \r
517                                                                 // add column to sort list\r
518                                                                 config.sortList.push([i,this.order]);\r
519                                                         \r
520                                                         // multi column sorting \r
521                                                         } else {\r
522                                                                 // the user has clicked on an all ready sortet column.\r
523                                                                 if(isValueInArray(i,config.sortList)) {  \r
524                                                                         \r
525                                                                         // revers the sorting direction for all tables.\r
526                                                                         for(var j=0; j < config.sortList.length; j++) {\r
527                                                                                 var s = config.sortList[j], o = config.headerList[s[0]];\r
528                                                                                 if(s[0] == i) {\r
529                                                                                         o.count = s[1];\r
530                                                                                         o.count++;\r
531                                                                                         s[1] = o.count % 2;\r
532                                                                                 }\r
533                                                                         }       \r
534                                                                 } else {\r
535                                                                         // add column to sort list array\r
536                                                                         config.sortList.push([i,this.order]);\r
537                                                                 }\r
538                                                         };\r
539                                                         \r
540                                                         //set css for headers\r
541                                                         setHeadersCss($this[0],$headers,config.sortList,sortCSS);\r
542                                                         \r
543                                                         // sort the table and append it to the dom\r
544                                                         appendToTable($this[0],multisort($this[0],config.sortList,cache));\r
545                                                         \r
546                                                         // stop normal event by returning false\r
547                                                         return false;\r
548                                                 }\r
549                                         // cancel selection     
550                                         }).mousedown(function() {\r
551                                                 if(config.cancelSelection) {\r
552                                                         this.onselectstart = function() {return false};\r
553                                                         //alert(this.onselectstart);\r
554                                                         return false;\r
555                                                 }\r
556                                         });\r
557                                         \r
558                                         // apply easy methods that trigger binded events\r
559                                         $this.bind("update",function() {\r
560                                                 \r
561                                                 // rebuild the cache map\r
562                                                 cache = buildCache(this);\r
563                                                 \r
564                                         }).bind("sorton",function(e,list) {\r
565                                                 \r
566                                                 // update and store the sortlist\r
567                                                 var sortList = config.sortList = list;\r
568                                                 \r
569                                                 // update header count index\r
570                                                 updateHeaderSortCount(this,sortList);\r
571                                                 \r
572                                                 //set css for headers\r
573                                                 setHeadersCss(this,$headers,sortList,sortCSS);\r
574                                                 \r
575                                                 // sort the table and append it to the dom\r
576                                                 appendToTable(this,multisort(this,sortList,cache));\r
577                                                 \r
578                                         }).bind("appendCache",function() {\r
579                                                 \r
580                                                 appendToTable(this,cache);\r
581                                         \r
582                                         }).bind("applyWidgetId",function(e,id) {\r
583                                                 \r
584                                                 getWidgetById(id).format(this);\r
585                                                 \r
586                                         });\r
587                                         \r
588                                         if($.meta && ($(this).data() && $(this).data().sortlist)) {\r
589                                                 config.sortList = $(this).data().sortlist;\r
590                                         }\r
591                                         // if user has supplied a sort list to constructor.\r
592                                         if(config.sortList.length > 0) {\r
593                                                 $this.trigger("sorton",[config.sortList]);      \r
594                                         }\r
595                                         \r
596                                         // apply widgets\r
597                                         applyWidget(this);\r
598                                 });\r
599                         };\r
600                         \r
601                         this.addParser = function(parser) {\r
602                                 var l = parsers.length, a = true;\r
603                                 for(var i=0; i < l; i++) {\r
604                                         if(parsers[i].id.toLowerCase() == parser.id.toLowerCase()) {\r
605                                                 a = false;\r
606                                         }\r
607                                 }\r
608                                 if(a) { parsers.push(parser); };\r
609                         };\r
610                         \r
611                         this.addWidget = function(widget) {\r
612                                 widgets.push(widget);\r
613                         };\r
614                         \r
615                         this.formatFloat = function(s) {\r
616 \r
617                                 var i = parseFloat(s);\r
618                                 return (isNaN(i)) ? 0 : i;\r
619                         };\r
620                         this.formatInt = function(s) {\r
621                                 var i = parseInt(s);\r
622                                 return (isNaN(i)) ? 0 : i;\r
623                         };\r
624                         \r
625                 }\r
626         });\r
627         \r
628         // extend plugin scope\r
629         $.fn.extend({\r
630         tablesorter: $.tablesorter.construct\r
631         });\r
632         \r
633         // add default parsers\r
634         $.tablesorter.addParser({\r
635                 id: "text",\r
636                 is: function(s) {\r
637                         return true;\r
638                 },\r
639                 format: function(s) {\r
640                         return $.trim(s.toLowerCase());\r
641                 },\r
642                 type: "text"\r
643         });\r
644         \r
645         $.tablesorter.addParser({\r
646                 id: "integer",\r
647                 is: function(s) {\r
648                         return s.match(new RegExp(/^\d+$/));\r
649                 },\r
650                 format: function(s) {\r
651                         return $.tablesorter.formatInt(s);\r
652                 },\r
653                 type: "numeric"\r
654         });\r
655         \r
656         $.tablesorter.addParser({\r
657                 id: "currency",\r
658                 is: function(s) {\r
659                         return /^[£$€?.]/.test(s);\r
660                 },\r
661                 format: function(s) {\r
662                         return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));\r
663                 },\r
664                 type: "numeric"\r
665         });\r
666         \r
667         $.tablesorter.addParser({\r
668                 id: "integer",\r
669                 is: function(s) {\r
670                         return /^\d+$/.test(s);\r
671                 },\r
672                 format: function(s) {\r
673                         return $.tablesorter.formatFloat(s);\r
674                 },\r
675                 type: "numeric"\r
676         });\r
677         \r
678         $.tablesorter.addParser({\r
679                 id: "floating",\r
680                 is: function(s) {\r
681                         return s.match(new RegExp(/^(\+|-)?[0-9]+\.[0-9]+((E|e)(\+|-)?[0-9]+)?$/));\r
682                 },\r
683                 format: function(s) {\r
684                         return $.tablesorter.formatFloat(s.replace(new RegExp(/,/),""));\r
685                 },\r
686                 type: "numeric"\r
687         });\r
688         \r
689         $.tablesorter.addParser({\r
690                 id: "ipAddress",\r
691                 is: function(s) {\r
692                         return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);\r
693                 },\r
694                 format: function(s) {\r
695                         var a = s.split(".");\r
696                         var r = "";\r
697                         for (var i = 0, item; item = a[i]; i++) {\r
698                            if(item.length == 2) {\r
699                                         r += "0" + item;\r
700                            } else {\r
701                                         r += item;\r
702                            }\r
703                         }\r
704                         return $.tablesorter.formatFloat(s);\r
705                 },\r
706                 type: "numeric"\r
707         });\r
708         \r
709         $.tablesorter.addParser({\r
710                 id: "url",\r
711                 is: function(s) {\r
712                         return /^(https?|ftp|file):\/\/$/.test(s);\r
713                 },\r
714                 format: function(s) {\r
715                         return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));\r
716                 },\r
717                 type: "text"\r
718         });\r
719         \r
720         $.tablesorter.addParser({\r
721                 id: "isoDate",\r
722                 is: function(s) {\r
723                         return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);\r
724                 },\r
725                 format: function(s) {\r
726                         return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(new RegExp(/-/g),"/")).getTime() : "0");\r
727                 },\r
728                 type: "numeric"\r
729         });\r
730         \r
731         $.tablesorter.addParser({\r
732                 id: "percent",\r
733                 is: function(s) {\r
734                         return /^\d{1,3}%$/.test(s);\r
735                 },\r
736                 format: function(s) {\r
737                         return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));\r
738                 },\r
739                 type: "numeric"\r
740         });\r
741         \r
742         $.tablesorter.addParser({\r
743                 id: "usLongDate",\r
744                 is: function(s) {\r
745                         return /^[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)))$/.test(s);\r
746                 },\r
747                 format: function(s) {\r
748                         return $.tablesorter.formatFloat(new Date(s).getTime());\r
749                 },\r
750                 type: "numeric"\r
751         });\r
752         \r
753         $.tablesorter.addParser({\r
754                 id: "shortDate",\r
755                 is: function(s) {\r
756                         return /\d{1,2}[\/-]\d{1,2}[\/-]\d{2,4}/.test(s);\r
757                 },\r
758                 format: function(s,table) {\r
759                         var c = table.config;\r
760                         s = s.replace(new RegExp(/-/g),"/");\r
761                         if(c.dateFormat == "us") {\r
762                                 /** reformat the string in ISO format */\r
763                                 s = s.replace(new RegExp(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{4})/), "$3/$1/$2");\r
764                         } else if(c.dateFormat == "uk") {\r
765                                 /** reformat the string in ISO format */\r
766                                 s = s.replace(new RegExp(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{4})/), "$3/$2/$1");\r
767                         } else if(c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") {\r
768                                 s = s.replace(new RegExp(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2})/), "$1/$2/$3");   \r
769                         }\r
770                         return $.tablesorter.formatFloat(new Date(s).getTime());\r
771                 },\r
772                 type: "numeric"\r
773         });\r
774         \r
775         $.tablesorter.addParser({\r
776             id: "time",\r
777             is: function(s) {\r
778                 return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);\r
779             },\r
780             format: function(s) {\r
781                 return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime());\r
782             },\r
783           type: "numeric"\r
784         });\r
785         \r
786         \r
787         $.tablesorter.addParser({\r
788             id: "metadata",\r
789             is: function(s) {\r
790                 return false;\r
791             },\r
792             format: function(s,table,cell) {\r
793                         var c = table.config, p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName;\r
794                 return $(cell).data()[p];\r
795             },\r
796           type: "numeric"\r
797         });\r
798         \r
799         // add default widgets\r
800         $.tablesorter.addWidget({\r
801                 id: "zebra",\r
802                 format: function(table) {\r
803                         $("> tbody:first/tr:visible:even",table).removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]);\r
804                         $("> tbody:first/tr:visible:odd",table).removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);\r
805                 }\r
806         });\r
807         \r
808 })(jQuery);