2 * From: http://www.kryogenix.org/code/browser/sorttable/
6 hookEvent( "load", sortables_init
);
9 var NO_ARROW
= stylepath
+'/common/sort_none.gif';
10 var UP_ARROW
= stylepath
+'/common/sort_up.gif';
11 var DOWN_ARROW
= stylepath
+'/common/sort_down.gif';
13 function sortables_init() {
15 // Find all tables with class sortable and make them sortable
16 if (!document
.getElementsByTagName
) return;
17 tbls
= document
.getElementsByTagName("table");
18 for (ti
=0;ti
<tbls
.length
;ti
++) {
20 if ((' '+thisTbl
.className
+' ').indexOf(" sortable ") != -1) {
22 thisTbl
.setAttribute('id','sortable_table_id_'+idnum
);
25 //initTable(thisTbl.id);
26 ts_makeSortable(thisTbl
);
31 function ts_makeSortable(table
) {
32 if (table
.rows
&& table
.rows
.length
> 0) {
33 var firstRow
= table
.rows
[0];
35 if (!firstRow
) return;
37 // We have a first row: assume it's the header, and make its contents clickable links
38 for (var i
=0;i
<firstRow
.cells
.length
;i
++) {
39 var cell
= firstRow
.cells
[i
];
40 var txt
= ts_getInnerText(cell
);
41 cell
.innerHTML
= txt
+'<a href="#" class="sortheader" onclick="ts_resortTable(this);return false;"><img class="sortarrow" src="'+NO_ARROW
+'" alt="↕" /></a>';
45 function ts_getInnerText(el
) {
46 if (typeof el
== "string") return el
;
47 if (typeof el
== "undefined") { return el
};
48 if (el
.innerText
) return el
.innerText
; //Not needed but it is faster
51 var cs
= el
.childNodes
;
53 for (var i
= 0; i
< l
; i
++) {
54 switch (cs
[i
].nodeType
) {
55 case 1: //ELEMENT_NODE
56 str
+= ts_getInnerText(cs
[i
]);
59 str
+= cs
[i
].nodeValue
;
66 function ts_resortTable(lnk
) {
67 // get the arrow image
69 for (var ci
=0;ci
<lnk
.childNodes
.length
;ci
++) {
70 if (lnk
.childNodes
[ci
].tagName
&& lnk
.childNodes
[ci
].tagName
.toLowerCase() == 'img') img
= lnk
.childNodes
[ci
];
72 var td
= lnk
.parentNode
;
73 var column
= td
.cellIndex
;
74 var table
= getParent(td
,'TABLE');
76 // Work out a type for the column
77 if (table
.rows
.length
<= 1) return;
78 var itm
= ts_getInnerText(table
.rows
[1].cells
[column
]);
79 sortfn
= ts_sort_caseinsensitive
;
80 // Note: The trailing \n$ is needed because that's how MediaWiki spits out its table syntax.
81 if (itm
.match(/^\s*\d{2}[\/-]\d{2}[\/-]\d{4}\s*$/)) sortfn
= ts_sort_date
;
82 if (itm
.match(/^\s*\d{2}[\/-]\d{2}[\/-]\d{2}\s*$/)) sortfn
= ts_sort_date
;
83 if (itm
.match(/^\s*[?$]/)) sortfn
= ts_sort_currency
;
84 if (itm
.match(/^\s*[\d\.]+\s*$/)) sortfn
= ts_sort_numeric
;
85 SORT_COLUMN_INDEX
= column
;
86 var firstRow
= new Array();
87 var newRows
= new Array();
88 for (i
=0;i
<table
.rows
[0].length
;i
++) { firstRow
[i
] = table
.rows
[0][i
]; }
89 for (j
=1;j
<table
.rows
.length
;j
++) { newRows
[j
-1] = table
.rows
[j
]; }
93 if (img
.getAttribute("sortdir") == 'down') {
96 img
.setAttribute('sortdir','up');
99 img
.setAttribute('sortdir','down');
102 // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
103 // don't do sortbottom rows
104 for (i
=0;i
<newRows
.length
;i
++) { if (!newRows
[i
].className
|| (newRows
[i
].className
&& (newRows
[i
].className
.indexOf('sortbottom') == -1))) table
.tBodies
[0].appendChild(newRows
[i
]);}
105 // do sortbottom rows only
106 for (i
=0;i
<newRows
.length
;i
++) { if (newRows
[i
].className
&& (newRows
[i
].className
.indexOf('sortbottom') != -1)) table
.tBodies
[0].appendChild(newRows
[i
]);}
108 // Delete any other arrows there may be showing
109 var allimgs
= document
.getElementsByTagName("img");
110 for (var ci
=0;ci
<allimgs
.length
;ci
++) {
111 if (allimgs
[ci
].className
== 'sortarrow') {
112 if (getParent(allimgs
[ci
],"table") == getParent(lnk
,"table")) { // in the same table as us?
113 allimgs
[ci
].setAttribute('src',NO_ARROW
);
118 img
.setAttribute('src',ARROW
);
119 img
.setAttribute('alt',img
.getAttribute("sortdir") == 'down' ? '↓' : '↑');
122 function getParent(el
, pTagName
) {
123 if (el
== null) return null;
124 else if (el
.nodeType
== 1 && el
.tagName
.toLowerCase() == pTagName
.toLowerCase()) // Gecko bug, supposed to be uppercase
127 return getParent(el
.parentNode
, pTagName
);
129 function ts_sort_date(a
,b
) {
130 // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
131 aa
= ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]);
132 bb
= ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]);
133 if (aa
.length
== 10) {
134 dt1
= aa
.substr(6,4)+aa
.substr(3,2)+aa
.substr(0,2);
137 if (parseInt(yr
) < 50) { yr
= '20'+yr
; } else { yr
= '19'+yr
; }
138 dt1
= yr
+aa
.substr(3,2)+aa
.substr(0,2);
140 if (bb
.length
== 10) {
141 dt2
= bb
.substr(6,4)+bb
.substr(3,2)+bb
.substr(0,2);
144 if (parseInt(yr
) < 50) { yr
= '20'+yr
; } else { yr
= '19'+yr
; }
145 dt2
= yr
+bb
.substr(3,2)+bb
.substr(0,2);
147 if (dt1
==dt2
) return 0;
148 if (dt1
<dt2
) return -1;
152 function ts_sort_currency(a
,b
) {
153 aa
= ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]).replace(/[^0-9.]/g,'');
154 bb
= ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]).replace(/[^0-9.]/g,'');
155 return parseFloat(aa
) - parseFloat(bb
);
158 function ts_sort_numeric(a
,b
) {
159 aa
= parseFloat(ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]));
160 if (isNaN(aa
)) aa
= 0;
161 bb
= parseFloat(ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]));
162 if (isNaN(bb
)) bb
= 0;
166 function ts_sort_caseinsensitive(a
,b
) {
167 aa
= ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]).toLowerCase();
168 bb
= ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]).toLowerCase();
169 if (aa
==bb
) return 0;
170 if (aa
<bb
) return -1;
174 function ts_sort_default(a
,b
) {
175 aa
= ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]);
176 bb
= ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]);
177 if (aa
==bb
) return 0;
178 if (aa
<bb
) return -1;