994154961b8c54c0a194c58ee452a269c9f2c70c
3 * A script that let you sort table columns by clicking on the header.
5 * Grabbed from: http://www.kryogenix.org/code/browser/sorttable/
8 * - C. David Eagle ( http://books.mingovia.org/ )
10 * getInnerText() function by Erik at http://webfx.eae.net/
12 * Some changes probably have been made by Avar
13 * http://bugzilla.wikimedia.org/show_bug.cgi?id=2001
23 addEvent(window
, "load", sortables_init
);
25 var SORT_COLUMN_INDEX
;
27 function sortables_init() {
28 // Find all tables with class sortable and make them sortable
29 if (!document
.getElementsByTagName
) return;
30 tbls
= document
.getElementsByTagName("table");
31 for (ti
=0;ti
<tbls
.length
;ti
++) {
33 if (((' '+thisTbl
.className
+' ').indexOf("sortable") != -1) && (thisTbl
.id
)) {
34 //initTable(thisTbl.id);
35 ts_makeSortable(thisTbl
);
40 function ts_makeSortable(table
) {
41 if (table
.rows
&& table
.rows
.length
> 0) {
42 var firstRow
= table
.rows
[0];
44 if (!firstRow
) return;
46 // We have a first row: assume it's the header, and make its contents clickable links
47 for (var i
=0;i
<firstRow
.cells
.length
;i
++) {
48 var cell
= firstRow
.cells
[i
];
49 /* Will get text of the element, breaking <a>
50 var txt = ts_getInnerText(cell);
52 cell
.innerHTML
= cell
.innerHTML
+'<a href="#" class="sortheader" onclick="ts_resortTable(this);return false;"><span class="sortarrow">↕</span></a>';
56 function ts_getInnerText(el
) {
57 if (typeof el
== "string") return el
;
58 if (typeof el
== "undefined") { return el
};
59 if (el
.innerText
) return el
.innerText
; //Not needed but it is faster
62 var cs
= el
.childNodes
;
64 for (var i
= 0; i
< l
; i
++) {
65 switch (cs
[i
].nodeType
) {
66 case 1: //ELEMENT_NODE
67 str
+= ts_getInnerText(cs
[i
]);
70 str
+= cs
[i
].nodeValue
;
77 function ts_resortTable(lnk
) {
80 for (var ci
=0;ci
<lnk
.childNodes
.length
;ci
++) {
81 if (lnk
.childNodes
[ci
].tagName
&& lnk
.childNodes
[ci
].tagName
.toLowerCase() == 'span') span
= lnk
.childNodes
[ci
];
83 var spantext
= ts_getInnerText(span
);
84 var td
= lnk
.parentNode
;
85 var column
= td
.cellIndex
;
86 var table
= getParent(td
,'TABLE');
88 // Work out a type for the column
89 if (table
.rows
.length
<= 1) return;
90 var itm
= ts_getInnerText(table
.rows
[1].cells
[column
]);
91 sortfn
= ts_sort_caseinsensitive
;
92 // Note: The trailing \n$ is needed because that's how MediaWiki spits out its table syntax.
93 if (itm
.match(/^\s*\d{2}[\/-]\d{2}[\/-]\d{4}\s*$/)) sortfn
= ts_sort_date
;
94 if (itm
.match(/^\s*\d{2}[\/-]\d{2}[\/-]\d{2}\s*$/)) sortfn
= ts_sort_date
;
96 if (itm.match(/^\s*[£¿$]/)) sortfn = ts_sort_currency;
98 if (itm
.match(/^\s*[\d\.\ ]+\s*$/)) sortfn
= ts_sort_numeric
;
99 SORT_COLUMN_INDEX
= column
;
100 var firstRow
= new Array();
101 var newRows
= new Array();
102 for (i
=0;i
<table
.rows
[0].length
;i
++) { firstRow
[i
] = table
.rows
[0][i
]; }
103 for (j
=1;j
<table
.rows
.length
;j
++) { newRows
[j
-1] = table
.rows
[j
]; }
105 newRows
.sort(sortfn
);
107 if (span
.getAttribute("sortdir") == 'down') {
110 span
.setAttribute('sortdir','up');
113 span
.setAttribute('sortdir','down');
116 // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
117 // don't do sortbottom rows
118 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
]);}
119 // do sortbottom rows only
120 for (i
=0;i
<newRows
.length
;i
++) { if (newRows
[i
].className
&& (newRows
[i
].className
.indexOf('sortbottom') != -1)) table
.tBodies
[0].appendChild(newRows
[i
]);}
122 // Delete any other arrows there may be showing
123 var allspans
= document
.getElementsByTagName("span");
124 for (var ci
=0;ci
<allspans
.length
;ci
++) {
125 if (allspans
[ci
].className
== 'sortarrow') {
126 if (getParent(allspans
[ci
],"table") == getParent(lnk
,"table")) { // in the same table as us?
127 allspans
[ci
].innerHTML
= '↕';
132 span
.innerHTML
= ARROW
;
135 function getParent(el
, pTagName
) {
136 if (el
== null) return null;
137 else if (el
.nodeType
== 1 && el
.tagName
.toLowerCase() == pTagName
.toLowerCase()) // Gecko bug, supposed to be uppercase
140 return getParent(el
.parentNode
, pTagName
);
142 function ts_sort_date(a
,b
) {
143 // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
144 aa
= ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]);
145 bb
= ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]);
146 if (aa
.length
== 10) {
147 dt1
= aa
.substr(6,4)+aa
.substr(3,2)+aa
.substr(0,2);
150 if (parseInt(yr
) < 50) { yr
= '20'+yr
; } else { yr
= '19'+yr
; }
151 dt1
= yr
+aa
.substr(3,2)+aa
.substr(0,2);
153 if (bb
.length
== 10) {
154 dt2
= bb
.substr(6,4)+bb
.substr(3,2)+bb
.substr(0,2);
157 if (parseInt(yr
) < 50) { yr
= '20'+yr
; } else { yr
= '19'+yr
; }
158 dt2
= yr
+bb
.substr(3,2)+bb
.substr(0,2);
160 if (dt1
==dt2
) return 0;
161 if (dt1
<dt2
) return -1;
165 function ts_sort_currency(a
,b
) {
166 aa
= ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]).replace(/[^0-9.]/g,'');
167 bb
= ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]).replace(/[^0-9.]/g,'');
168 return parseFloat(aa
) - parseFloat(bb
);
171 function ts_sort_numeric(a
,b
) {
172 aa
= parseFloat(ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]));
173 if (isNaN(aa
)) aa
= 0;
174 bb
= parseFloat(ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]));
175 if (isNaN(bb
)) bb
= 0;
179 function ts_sort_caseinsensitive(a
,b
) {
180 aa
= ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]).toLowerCase();
181 bb
= ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]).toLowerCase();
182 if (aa
==bb
) return 0;
183 if (aa
<bb
) return -1;
187 function ts_sort_default(a
,b
) {
188 aa
= ts_getInnerText(a
.cells
[SORT_COLUMN_INDEX
]);
189 bb
= ts_getInnerText(b
.cells
[SORT_COLUMN_INDEX
]);
190 if (aa
==bb
) return 0;
191 if (aa
<bb
) return -1;
196 function addEvent(elm
, evType
, fn
, useCapture
)
197 // addEvent and removeEvent
198 // cross-browser event handling for IE5+, NS6 and Mozilla
201 if (elm
.addEventListener
){
202 elm
.addEventListener(evType
, fn
, useCapture
);
204 } else if (elm
.attachEvent
){
205 var r
= elm
.attachEvent("on"+evType
, fn
);
208 alert("Handler could not be removed");