2
Table sorting script by Joost de Valk, check it out at http://www.joostdevalk.nl/code/sortable-table/.
3
Based on a script from http://www.kryogenix.org/code/browser/sorttable/.
4
Distributed under the MIT license: http://www.kryogenix.org/code/browser/licence.html .
5
Modify by the MG team for compatibility issue
7
Copyright (c) 1997-2007 Stuart Langridge, Joost de Valk.
12
/* You can change these values */
13
var europeandate = true;
14
var alternate_row_colors = true;
16
/* Don't change anything below this unless you know what you're doing */
17
addEvent(window, "load", sortables_init);
19
var SORT_COLUMN_INDEX;
22
function sortables_init() {
23
// Find all tables with class sortable and make them sortable
24
if (!document.getElementsByTagName) return;
25
tbls = document.getElementsByTagName("table");
26
for (ti=0;ti<tbls.length;ti++) {
28
if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
29
ts_makeSortable(thisTbl);
30
// make it sortable according to the second column
31
if (thisTbl.tHead && thisTbl.tHead.rows.length > 0) {
32
var firstRow = thisTbl.tHead.rows[thisTbl.tHead.rows.length-1];
34
var firstRow = thisTbl.rows[0];
37
for (var ci=0;ci<firstRow.cells[1].childNodes.length;ci++) {
38
if (firstRow.cells[1].childNodes[ci].tagName && firstRow.cells[1].childNodes[ci].tagName.toLowerCase() == 'a') var lnk = firstRow.cells[1].childNodes[ci];
40
ts_resortTable(lnk, 1); //order by cross-section
41
ts_resortTable(lnk, 1); //order by cross-section
46
function ts_makeSortable(t) {
47
if (t.rows && t.rows.length > 0) {
48
if (t.tHead && t.tHead.rows.length > 0) {
49
var firstRow = t.tHead.rows[t.tHead.rows.length-1];
52
var firstRow = t.rows[0];
55
if (!firstRow) return;
57
// We have a first row: assume it's the header, and make its contents clickable links
58
for (var i=0;i<firstRow.cells.length;i++) {
59
var cell = firstRow.cells[i];
60
var txt = ts_getInnerText(cell);
61
if (cell.className != "unsortable" && cell.className.indexOf("unsortable") == -1) {
62
cell.innerHTML = '<a href="#" class="sortheader" onclick="ts_resortTable(this, '+i+');return false;">'+txt+'<span class="sortarrow"></span></a>';
65
if (alternate_row_colors) {
70
function ts_getInnerText(el) {
71
if (typeof el == "string") return el;
72
if (typeof el == "undefined") { return el };
73
if (el.innerText) return el.innerText; //Not needed but it is faster
76
var cs = el.childNodes;
78
for (var i = 0; i < l; i++) {
79
switch (cs[i].nodeType) {
80
case 1: //ELEMENT_NODE
81
str += ts_getInnerText(cs[i]);
84
str += cs[i].nodeValue;
91
function ts_resortTable(lnk, clid) {
93
for (var ci=0;ci<lnk.childNodes.length;ci++) {
94
if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
96
var spantext = ts_getInnerText(span);
97
var td = lnk.parentNode;
98
var column = clid || td.cellIndex;
99
var t = getParent(td,'TABLE');
100
// Work out a type for the column
101
if (t.rows.length <= 1) return;
104
while (itm == "" && i < t.tBodies[0].rows.length) {
105
var itm = ts_getInnerText(t.tBodies[0].rows[i].cells[column]);
107
if (itm.substr(0,4) == "<!--" || itm.length == 0) {
112
if (itm == "") return;
113
sortfn = ts_sort_caseinsensitive;
114
if (itm.match(/^\d\d[\/\.-][a-zA-z][a-zA-Z][a-zA-Z][\/\.-]\d\d\d\d$/)) sortfn = ts_sort_date;
115
if (itm.match(/^\d\d[\/\.-]\d\d[\/\.-]\d\d\d{2}?$/)) sortfn = ts_sort_date;
116
if (itm.match(/^-?[�$�ۢ�]\d/)) sortfn = ts_sort_numeric;
117
if (itm.match(/^-?(\d+[,\.]?)+(E[-+][\d]+)?%?$/)) sortfn = ts_sort_numeric;
118
if (itm.match(/^-?(\d+[,\.]?\d+e[-+][\d]+)?%?$/)) sortfn = ts_sort_numeric;
119
if (itm.match(/^-?(\d+[,\.]?)+([\d]+)?%?$/)) sortfn = ts_sort_numeric;
120
SORT_COLUMN_INDEX = column;
121
var firstRow = new Array();
122
var newRows = new Array();
123
for (k=0;k<t.tBodies.length;k++) {
124
for (i=0;i<t.tBodies[k].rows[0].length;i++) {
125
firstRow[i] = t.tBodies[k].rows[0][i];
128
for (k=0;k<t.tBodies.length;k++) {
130
// Skip the first row
131
for (j=1;j<t.tBodies[k].rows.length;j++) {
132
newRows[j-1] = t.tBodies[k].rows[j];
135
// Do NOT skip the first row
136
for (j=0;j<t.tBodies[k].rows.length;j++) {
137
newRows[j] = t.tBodies[k].rows[j];
141
newRows.sort(sortfn);
142
if (span.getAttribute("sortdir") == 'down') {
143
ARROW = ' ↓';
145
span.setAttribute('sortdir','up');
147
ARROW = ' ↑';
148
span.setAttribute('sortdir','down');
150
// We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
151
// don't do sortbottom rows
152
for (i=0; i<newRows.length; i++) {
153
if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) {
154
t.tBodies[0].appendChild(newRows[i]);
157
// do sortbottom rows only
158
for (i=0; i<newRows.length; i++) {
159
if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1))
160
t.tBodies[0].appendChild(newRows[i]);
162
// Delete any other arrows there may be showing
163
var allspans = document.getElementsByTagName("span");
164
for (var ci=0;ci<allspans.length;ci++) {
165
if (allspans[ci].className == 'sortarrow') {
166
if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
167
allspans[ci].innerHTML = '';
171
span.innerHTML = ARROW;
175
function getParent(el, pTagName) {
178
} else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) {
181
return getParent(el.parentNode, pTagName);
185
function sort_date(date) {
186
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
188
if (date.length == 11) {
189
mtstr = date.substr(3,3);
190
mtstr = mtstr.toLowerCase();
192
case "jan": var mt = "01"; break;
193
case "feb": var mt = "02"; break;
194
case "mar": var mt = "03"; break;
195
case "apr": var mt = "04"; break;
196
case "may": var mt = "05"; break;
197
case "jun": var mt = "06"; break;
198
case "jul": var mt = "07"; break;
199
case "aug": var mt = "08"; break;
200
case "sep": var mt = "09"; break;
201
case "oct": var mt = "10"; break;
202
case "nov": var mt = "11"; break;
203
case "dec": var mt = "12"; break;
204
// default: var mt = "00";
206
dt = date.substr(7,4)+mt+date.substr(0,2);
208
} else if (date.length == 10) {
209
if (europeandate == false) {
210
dt = date.substr(6,4)+date.substr(0,2)+date.substr(3,2);
213
dt = date.substr(6,4)+date.substr(3,2)+date.substr(0,2);
216
} else if (date.length == 8) {
217
yr = date.substr(6,2);
218
if (parseInt(yr) < 50) {
223
if (europeandate == true) {
224
dt = yr+date.substr(3,2)+date.substr(0,2);
227
dt = yr+date.substr(0,2)+date.substr(3,2);
234
function ts_sort_date(a,b) {
235
dt1 = sort_date(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
236
dt2 = sort_date(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
246
function ts_sort_numeric(a,b) {
247
var aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
249
var bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
251
return compare_numeric(aa,bb);
253
function compare_numeric(a,b) {
254
var a = parseFloat(a);
255
a = (isNaN(a) ? 0 : a);
256
var b = parseFloat(b);
257
b = (isNaN(b) ? 0 : b);
260
function ts_sort_caseinsensitive(a,b) {
261
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
262
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
271
function ts_sort_default(a,b) {
272
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
273
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
283
function addEvent(elm, evType, fn, useCapture)
284
// addEvent and removeEvent
285
// cross-browser event handling for IE5+, NS6 and Mozilla
288
if (elm.addEventListener){
289
elm.addEventListener(evType, fn, useCapture);
291
} else if (elm.attachEvent){
292
var r = elm.attachEvent("on"+evType, fn);
295
alert("Handler could not be removed");
298
function clean_num(str) {
299
str = str.replace(new RegExp(/[^-?0-9.eE]/g),"");
303
return s.replace(/^\s+|\s+$/g, "");
305
function alternate(table) {
306
// Take object table and get all it's tbodies.
307
var tableBodies = table.getElementsByTagName("tbody");
308
// Loop through these tbodies
309
for (var i = 0; i < tableBodies.length; i++) {
310
// Take the tbody, and get all it's rows
311
var tableRows = tableBodies[i].getElementsByTagName("tr");
312
// Loop through these rows
313
// Start at 1 because we want to leave the heading row untouched
314
for (var j = 0; j < tableRows.length; j++) {
315
// Check if j is even, and apply classes for both possible results
316
if ( (j % 2) == 0 ) {
317
if ( !(tableRows[j].className.indexOf('odd') == -1) ) {
318
tableRows[j].className = tableRows[j].className.replace('odd', 'even');
320
if ( tableRows[j].className.indexOf('even') == -1 ) {
321
tableRows[j].className += " even";
325
if ( !(tableRows[j].className.indexOf('even') == -1) ) {
326
tableRows[j].className = tableRows[j].className.replace('even', 'odd');
328
if ( tableRows[j].className.indexOf('odd') == -1 ) {
329
tableRows[j].className += " odd";