Add pretty arrow images from SMW for sorttable instead of Unicode arrow characters...
[lhc/web/wiklou.git] / skins / common / sorttable.js
1 /*
2 * From: http://www.kryogenix.org/code/browser/sorttable/
3 * Licence: X11
4 */
5
6 addEvent(window, "load", sortables_init);
7
8 var SORT_COLUMN_INDEX;
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';
12
13 function sortables_init() {
14 var idnum = 0;
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++) {
19 thisTbl = tbls[ti];
20 if ((' '+thisTbl.className+' ').indexOf("sortable") != -1) {
21 if (!thisTbl.id) {
22 thisTbl.setAttribute('id','sortable_table_id_'+idnum);
23 ++idnum;
24 }
25 //initTable(thisTbl.id);
26 ts_makeSortable(thisTbl);
27 }
28 }
29 }
30
31 function ts_makeSortable(table) {
32 if (table.rows && table.rows.length > 0) {
33 var firstRow = table.rows[0];
34 }
35 if (!firstRow) return;
36
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="&#x2195;" /></a>';
42 }
43 }
44
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
49 var str = "";
50
51 var cs = el.childNodes;
52 var l = cs.length;
53 for (var i = 0; i < l; i++) {
54 switch (cs[i].nodeType) {
55 case 1: //ELEMENT_NODE
56 str += ts_getInnerText(cs[i]);
57 break;
58 case 3: //TEXT_NODE
59 str += cs[i].nodeValue;
60 break;
61 }
62 }
63 return str;
64 }
65
66 function ts_resortTable(lnk) {
67 // get the arrow image
68 var img;
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];
71 }
72 var td = lnk.parentNode;
73 var column = td.cellIndex;
74 var table = getParent(td,'TABLE');
75
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]; }
90
91 newRows.sort(sortfn);
92
93 if (img.getAttribute("sortdir") == 'down') {
94 ARROW = UP_ARROW;
95 newRows.reverse();
96 img.setAttribute('sortdir','up');
97 } else {
98 ARROW = DOWN_ARROW;
99 img.setAttribute('sortdir','down');
100 }
101
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]);}
107
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);
114 }
115 }
116 }
117
118 img.setAttribute('src',ARROW);
119 img.setAttribute('alt',img.getAttribute("sortdir") == 'down' ? '&darr;' : '&uarr;');
120 }
121
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
125 return el;
126 else
127 return getParent(el.parentNode, pTagName);
128 }
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);
135 } else {
136 yr = aa.substr(6,2);
137 if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
138 dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
139 }
140 if (bb.length == 10) {
141 dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
142 } else {
143 yr = bb.substr(6,2);
144 if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
145 dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
146 }
147 if (dt1==dt2) return 0;
148 if (dt1<dt2) return -1;
149 return 1;
150 }
151
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);
156 }
157
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;
163 return aa-bb;
164 }
165
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;
171 return 1;
172 }
173
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;
179 return 1;
180 }
181
182
183 function addEvent(elm, evType, fn, useCapture)
184 // addEvent and removeEvent
185 // cross-browser event handling for IE5+, NS6 and Mozilla
186 // By Scott Andrew
187 {
188 if (elm.addEventListener){
189 elm.addEventListener(evType, fn, useCapture);
190 return true;
191 } else if (elm.attachEvent){
192 var r = elm.attachEvent("on"+evType, fn);
193 return r;
194 } else {
195 alert("Handler could not be removed");
196 }
197 }