/* This is the Friendly Table Sorter, by Tony Boyd: http://www.outshine.com/ It is based upon a script by Joost de Valk: http://www.joostdevalk.nl/code/sortable-table/ And Joost's script was based upon a script by Stuart Langridge: http://www.kryogenix.org/code/browser/sorttable/ All three scripts are distributed under the MIT license: http://www.kryogenix.org/code/browser/licence.html Copyright 1997-2008 Stuart Langridge, Joost de Valk, Tony Boyd. Version 1.0.0 Released 2008-jun-04 Changelog: * Doesn't accidentally use the table header to try to determine the sort type. * Space allowed as separator between date fields. * Created sort type override feature. * Replaced broken arrow images with arrow glyph from standard font. * Refactored into a namespace so that there are no name collisions. * Better handling of US vs. non-US number formats. * Better handling of currency. * Faster trim function (imperceptible). * Cleaner sorting code (not faster, just neater). * Consistent naming convention for functions/methods. * Very clear comments to walk you through the code. */ var outshine = { /* These initial variables can be changed as follows: europeanDate -> true if dates are DD-MM-YYYY or DD-MM-YY europeanDate -> false if dates are MM-DD-YYYY or MM-DD-YY numberSeparator -> ',' for US syntax (1,000,000) alternateRowColors -> true for a light-dark color set for your table rows alternateRowColors -> false if you don't use alternating row colors You need to put 2 classes into your CSS to affect the row colors: rowlight -> a light color rowdark -> a different color */ europeanDate: false, numberSeparator: ',', alternateRowColors: true, /* From here on down, probably don't change stuff. Geek note: if you're trying to read the code, the control flow is reversed, so read bottom-up. */ SORT_COLUMN_INDEX: null, headerExists: false, /* This is a long but accurate list of currency symbols, in Unicode syntax. */ currencySymbols: /[\x24\u0024\u00a2\u00a3\u00a4\u00a5\u20a0\u20a1\u20a2\u20a3\u20a4\u20a5\u20a6\u20a7\u20a8\u20a9\u20aa\u20ab\u20ac\u20ad\u20ae\u20af\u20b0\u20b1]/g, ts_cleanNum: function(data) { /* Converts a string to a number. If conversion doesn't work, it returns 0. */ var numSeparator = new RegExp(this.numberSeparator, 'g'); data = parseFloat(data.replace(this.currencySymbols, '').replace(numSeparator, '')); return (isNaN(data)) ? 0 : data; }, ts_convertDate: function(date) { /* Feed this a string that looks like a date and it will attempt to convert it into a number in this format: YYYYMMDD. For example, 20090131. */ var dt = '00000000'; if (date.length == 11) { var mtstr = date.substr(3,3); mtstr = mtstr.toLowerCase(); var mt = '00'; switch(mtstr) { case 'jan': mt = '01'; break; case 'feb': mt = '02'; break; case 'mar': mt = '03'; break; case 'apr': mt = '04'; break; case 'may': mt = '05'; break; case 'jun': mt = '06'; break; case 'jul': mt = '07'; break; case 'aug': mt = '08'; break; case 'sep': mt = '09'; break; case 'oct': mt = '10'; break; case 'nov': mt = '11'; break; case 'dec': mt = '12'; break; } dt = date.substr(7,4) + mt + date.substr(0,2); return dt; } else if (date.length == 10) { if (this.europeanDate == false) { dt = date.substr(6,4) + date.substr(0,2) + date.substr(3,2); return dt; } else { dt = date.substr(6,4) + date.substr(3,2) + date.substr(0,2); return dt; } } else if (date.length == 8) { var yr = date.substr(6,2); /* Two-digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX. */ if (parseInt(yr) < 50) { yr = '20' + yr; } else { yr = '19' + yr; } if (this.europeanDate == true) { dt = yr + date.substr(3,2) + date.substr(0,2); return dt; } else { dt = yr + date.substr(0,2) + date.substr(3,2); return dt; } } return dt; }, ts_sortDate: function(a, b) { /* Get the contents of the a & b fields, do some clean up, convert the dates to numbers, compare numbers. */ var aa = this.ts_getInnerText(a.cells[this.SORT_COLUMN_INDEX]); aa = this.ts_trim(aa); aa = this.ts_convertDate(aa); aa = this.ts_cleanNum(aa); var bb = this.ts_getInnerText(b.cells[this.SORT_COLUMN_INDEX]); bb = this.ts_trim(bb); bb = this.ts_convertDate(bb); bb = this.ts_cleanNum(bb); return aa - bb; }, ts_sortNumeric: function(a, b) { /* Get the contents of the a & b fields, do some clean up, compare numbers. */ var aa = this.ts_getInnerText(a.cells[this.SORT_COLUMN_INDEX]); aa = this.ts_trim(aa); aa = this.ts_cleanNum(aa); var bb = this.ts_getInnerText(b.cells[this.SORT_COLUMN_INDEX]); bb = this.ts_trim(bb); bb = this.ts_cleanNum(bb); return aa - bb; }, ts_sortCaseInsensitive: function(a, b) { /* Lowercase the strings then compare them. */ var aa = this.ts_getInnerText(a.cells[this.SORT_COLUMN_INDEX]).toLowerCase(); var bb = this.ts_getInnerText(b.cells[this.SORT_COLUMN_INDEX]).toLowerCase(); if (aa==bb) { return 0; } if (aa 0) { if (t.tHead && t.tHead.rows.length > 0) { var firstRow = t.tHead.rows[t.tHead.rows.length-1]; this.headerExists = true; } else { var firstRow = t.rows[0]; } } if (!firstRow) return; /* A header exists, so make its contents clickable links. */ for (var i=0;i'+txt+' ↓'; } } /* Colorize the rows. */ if (this.alternateRowColors) { this.ts_colorizeRows(t); } }, ts_init: function() { /* Find all tables with a class of "sortable" and make them sortable. */ if (!document.getElementsByTagName) { return; } var tbls = document.getElementsByTagName('table'); for (var ti=0; ti