2 TableSort revisited v5.0 by frequency-decoder.com
4 Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)
6 Please credit frequency decoder in any derivative work - thanks
10 * to copy, distribute, display, and perform the work
11 * to make derivative works
12 * to make commercial use of the work
14 Under the following conditions:
18 You must attribute the work in the manner specified by the author or licensor.
22 Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.
24 * For any reuse or distribution, you must make clear to others the license terms of this work.
25 * Any of these conditions can be waived if you get permission from the copyright holder.
32 regExp_Currency: /^[£$€¥¤]/,
33 regExp_Number: /^(\-)?[0-9]+(\.[0-9]*)?$/,
40 sortActiveClass: "sort-active",
51 addEvent: function(obj, type, fn, tmp) {
53 if( obj.attachEvent ) {
54 obj["e"+type+fn] = fn;
55 obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
56 obj.attachEvent( "on"+type, obj[type+fn] );
58 obj.addEventListener( type, fn, true );
61 removeEvent: function(obj, type, fn, tmp) {
64 if( obj.detachEvent ) {
65 obj.detachEvent( "on"+type, obj[type+fn] );
68 obj.removeEventListener( type, fn, true );
72 stopEvent: function(e) {
73 e = e || window.event;
75 if(e.stopPropagation) {
82 e.cancelBubble = true;
83 e.returnValue = false;
87 parseClassName: function(head, tbl) {
88 var colMatch = tbl.className.match(new RegExp(head + "((-[\\d]+([r]){0,1})+)"));
89 return colMatch && colMatch.length ? colMatch[0].replace(head, "").split("-") : [];
91 disableSelection: function(element) {
92 element.onselectstart = function() {
95 element.unselectable = "on";
96 element.style.MozUserSelect = "none";
98 removeTableCache: function(tableId) {
99 if(!(tableId in fdTableSort.tableCache)) return;
101 fdTableSort.tableCache[tableId] = null;
102 delete fdTableSort.tableCache[tableId];
104 var tbl = document.getElementById(tableId);
106 var ths = tbl.getElementsByTagName("th");
108 for(var i = 0, th; th = ths[i]; i++) {
109 a = th.getElementsByTagName("a");
110 if(a.length) a[0].onkeydown = a[0].onclick = null;
111 th.onclick = th.onselectstart = th = a = null;
114 removeTmpCache: function(tableId) {
115 if(!(tableId in fdTableSort.tmpCache)) return;
116 var headers = fdTableSort.tmpCache[tableId].headers;
118 for(var i = 0, row; row = headers[i]; i++) {
119 for(var j = 0, th; th = row[j]; j++) {
120 a = th.getElementsByTagName("a");
121 if(a.length) a[0].onkeydown = a[0].onclick = null;
122 th.onclick = th.onselectstart = th = a = null;
125 fdTableSort.tmpCache[tableId] = null;
126 delete fdTableSort.tmpCache[tableId];
128 initEvt: function(e) {
129 fdTableSort.init(false);
131 init: function(tableId) {
132 if (debug) plc_message ('entering tablesort.init');
133 if (!document.getElementsByTagName || !document.createElement || !document.getElementById) return;
135 var tables = tableId && document.getElementById(tableId) ? [document.getElementById(tableId)] : document.getElementsByTagName("table");
136 var c, ii, len, colMatch, showOnly, match, showArrow, columnNumSortObj, obj, workArr, headers, thtext, aclone, multi, colCnt, cel, allRowArr, rowArr, sortableTable, celCount, colspan, rowspan, rowLength;
138 var a = document.createElement("a");
140 a.className = "fdTableSortTrigger";
142 var span = document.createElement("span");
144 for(var k = 0, tbl; tbl = tables[k]; k++) {
147 fdTableSort.removeTableCache(tbl.id);
148 fdTableSort.removeTmpCache(tbl.id);
151 allRowArr = tbl.getElementsByTagName('thead').length ? tbl.getElementsByTagName('thead')[0].getElementsByTagName('tr') : tbl.getElementsByTagName('tr');
153 sortableTable = false;
155 for(var i = 0, tr; tr = allRowArr[i]; i++) {
156 if(tr.getElementsByTagName('td').length || !tr.getElementsByTagName('th').length) { continue; };
157 rowArr[rowArr.length] = tr.getElementsByTagName('th');
158 for(var j = 0, th; th = rowArr[rowArr.length - 1][j]; j++) {
159 if(th.className.search(/sortable/) != -1) { sortableTable = true; };
163 if(!sortableTable) continue;
165 if(!tbl.id) { tbl.id = "fd-table-" + fdTableSort.uniqueHash++; };
167 showArrow = tbl.className.search("no-arrow") == -1;
168 showOnly = tbl.className.search("sortable-onload-show") != -1;
170 columnNumSortObj = {};
171 colMatch = fdTableSort.parseClassName(showOnly ? "sortable-onload-show" : "sortable-onload", tbl);
172 for(match = 1; match < colMatch.length; match++) {
173 columnNumSortObj[parseInt(colMatch[match], 10)] = { "reverse":colMatch[match].search("r") != -1 };
176 rowLength = rowArr[0].length;
178 for(c = 0;c < rowArr[0].length;c++){
179 if(rowArr[0][c].getAttribute(fdTableSort.colspan) && rowArr[0][c].getAttribute(fdTableSort.colspan) > 1){
180 rowLength = rowLength + (rowArr[0][c].getAttribute(fdTableSort.colspan) - 1);
184 workArr = new Array(rowArr.length);
185 for(c = rowArr.length;c--;){ workArr[c]= new Array(rowLength); };
187 for(c = 0;c < workArr.length;c++){
189 for(i = 0;i < rowLength;i++){
191 cel = rowArr[c][celCount];
192 colspan = (cel.getAttribute(fdTableSort.colspan) > 1) ? cel.getAttribute(fdTableSort.colspan):1;
193 rowspan = (cel.getAttribute(fdTableSort.rowspan) > 1) ? cel.getAttribute(fdTableSort.rowspan):1;
194 for(var t = 0;((t < colspan)&&((i+t) < rowLength));t++){
195 for(var n = 0;((n < rowspan)&&((c+n) < workArr.length));n++) {
196 workArr[(c+n)][(i+t)] = cel;
199 if(++celCount == rowArr[c].length) break;
204 for(c = 0;c < workArr.length;c++) {
205 for(i = 0;i < workArr[c].length;i++){
207 if(workArr[c][i].className.search("fd-column-") == -1 && workArr[c][i].className.search("sortable") != -1) workArr[c][i].className = workArr[c][i].className + " fd-column-" + i;
209 if(workArr[c][i].className.match('sortable')) {
210 workArr[c][i].className = workArr[c][i].className.replace(/forwardSort|reverseSort/, "");
212 if(i in columnNumSortObj) {
213 columnNumSortObj[i]["thNode"] = workArr[c][i];
214 columnNumSortObj["active"] = true;
217 thtext = fdTableSort.getInnerText(workArr[c][i], true);
219 for(var cn = workArr[c][i].childNodes.length; cn--;) {
220 // Skip image nodes and links created by the filter script.
221 if(workArr[c][i].childNodes[cn].nodeType == 1 && (workArr[c][i].childNodes[cn].className == "fdFilterTrigger" || /img/i.test(workArr[c][i].childNodes[cn].nodeName))) {
224 if(workArr[c][i].childNodes[cn].nodeType == 1 && /^a$/i.test(workArr[c][i].childNodes[cn].nodeName)) {
225 workArr[c][i].childNodes[cn].onclick = workArr[c][i].childNodes[cn].onkeydown = null;
227 workArr[c][i].removeChild(workArr[c][i].childNodes[cn]);
230 aclone = a.cloneNode(true);
231 //aclone.appendChild(document.createTextNode(thtext));
232 aclone.innerHTML = thtext;
233 aclone.title = "Sort on \u201c" + thtext.replace('<br />', '') + "\u201d";
234 aclone.onclick = aclone.onkeydown = workArr[c][i].onclick = fdTableSort.initWrapper;
235 workArr[c][i].appendChild(aclone);
236 if(showArrow) workArr[c][i].appendChild(span.cloneNode(false));
237 workArr[c][i].className = workArr[c][i].className.replace(/fd-identical|fd-not-identical/, "");
238 fdTableSort.disableSelection(workArr[c][i]);
244 fdTableSort.tmpCache[tbl.id] = {cols:rowLength, headers:workArr};
249 if("active" in columnNumSortObj) {
250 fdTableSort.tableId = tbl.id;
251 fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId));
253 delete columnNumSortObj["active"];
255 for(col in columnNumSortObj) {
256 obj = columnNumSortObj[col];
257 if(!("thNode" in obj)) { continue; };
258 fdTableSort.multi = true;
260 len = obj.reverse ? 2 : 1;
262 for(ii = 0; ii < len; ii++) {
263 fdTableSort.thNode = obj.thNode;
265 fdTableSort.initSort(false, true);
267 fdTableSort.addThNode();
272 fdTableSort.removeClass(obj.thNode, "(forwardSort|reverseSort)");
273 fdTableSort.addClass(obj.thNode, obj.reverse ? "reverseSort" : "forwardSort");
275 span = fdTableSort.thNode.getElementsByTagName('span')[0];
276 if(span.firstChild) { span.removeChild(span.firstChild); };
277 span.appendChild(document.createTextNode(len == 1 ? " \u2193" : " \u2191"));
281 if(showOnly && (fdTableSort.tableCache[tbl.id].colStyle || fdTableSort.tableCache[tbl.id].rowStyle)) {
282 fdTableSort.redraw(tbl.id, false);
284 } else if(tbl.className.search(/onload-zebra/) != -1) {
285 fdTableSort.tableId = tbl.id;
286 fdTableSort.prepareTableData(tbl);
287 if(fdTableSort.tableCache[tbl.id].rowStyle) { fdTableSort.redraw(tbl.id, false); };
291 fdTableSort.thNode = aclone = a = span = columnNumSortObj = thNode = tbl = allRowArr = rowArr = null;
292 if (debug) plc_message ('exiting tablesort.init');
294 initWrapper: function(e) {
295 e = e || window.event;
296 var kc = e.type == "keydown" ? e.keyCode != null ? e.keyCode : e.charCode : -1;
297 if(fdTableSort.thNode == null && (e.type == "click" || kc == 13)) {
299 while(targ.tagName.toLowerCase() != "th") { targ = targ.parentNode; };
300 fdTableSort.thNode = targ;
301 while(targ.tagName.toLowerCase() != "table") { targ = targ.parentNode; };
302 fdTableSort.tableId = targ.id;
303 fdTableSort.multi = e.shiftKey;
304 fdTableSort.addSortActiveClass();
305 setTimeout(fdTableSort.initSort,5,false);
306 return fdTableSort.stopEvent(e);
308 return kc != -1 ? true : fdTableSort.stopEvent(e);
310 jsWrapper: function(tableid, colNums) {
311 if(!(tableid in fdTableSort.tmpCache)) { return false; };
312 if(!(tableid in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(tableid)); };
313 if(!(colNums instanceof Array)) { colNums = [colNums]; };
315 fdTableSort.tableId = tableid;
316 var len = colNums.length, colNum;
318 if(fdTableSort.tableCache[tableid].thList.length == colNums.length) {
319 var identical = true;
321 for(var i = 0; i < len; i++) {
323 th = fdTableSort.tmpCache[tableid].headers[0][colNum];
324 if(th != fdTableSort.tableCache[tableid].thList[i]) {
330 fdTableSort.thNode = th;
331 fdTableSort.initSort(true);
336 fdTableSort.addSortActiveClass();
338 for(var i = 0; i < len; i++) {
339 fdTableSort.multi = i;
341 fdTableSort.thNode = fdTableSort.tmpCache[tableid].headers[0][colNum];
342 fdTableSort.initSort(true);
345 addSortActiveClass: function() {
346 if(fdTableSort.thNode == null) { return; };
347 fdTableSort.addClass(fdTableSort.thNode, fdTableSort.sortActiveClass);
348 fdTableSort.addClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass);
350 removeSortActiveClass: function() {
351 if(fdTableSort.thNode == null) return;
352 fdTableSort.removeClass(fdTableSort.thNode, fdTableSort.sortActiveClass);
353 fdTableSort.removeClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass);
355 doCallback: function(init) {
356 if(!fdTableSort.tableId || !(fdTableSort.tableId in fdTableSort.tableCache)) { return; };
357 fdTableSort.callback(fdTableSort.tableId, init ? fdTableSort.tableCache[fdTableSort.tableId].initiatedCallback : fdTableSort.tableCache[fdTableSort.tableId].completeCallback);
359 addClass: function(e,c) {
360 if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) { return; };
361 e.className += ( e.className ? " " : "" ) + c;
365 removeClass: function(e,c) {
366 e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');
369 removeClass: function(e,c) {
370 e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
374 callback: function(tblId, cb) {
377 if(cb.indexOf(".") != -1) {
378 parts = cb.split('.');
380 for (var x = 0, part; part = obj[parts[x]]; x++) {
381 if(part instanceof Function) {
384 func = function (data) { method.apply(obj, [data]) };
390 } else if(cb + tblId in window) {
391 func = window[cb + tblId];
392 } else if(cb in window) {
399 if(!(func instanceof Function)) return;
400 func(tblId, fdTableSort.tableCache[tblId].thList);
402 prepareTableData: function(table) {
405 var start = table.getElementsByTagName('tbody');
406 start = start.length ? start[0] : table;
408 var trs = start.rows;
409 var ths = table.getElementsByTagName('th');
411 var numberOfRows = trs.length;
412 var numberOfCols = fdTableSort.tmpCache[table.id].cols;
415 var identical = new Array(numberOfCols);
416 var identVal = new Array(numberOfCols);
418 for(var tmp = 0; tmp < numberOfCols; tmp++) identical[tmp] = true;
420 var tr, td, th, txt, tds, col, row;
422 var re = new RegExp(/fd-column-([0-9]+)/);
425 var sortableColumnNumbers = [];
427 for(var tmp = 0, th; th = ths[tmp]; tmp++) {
428 if(th.className.search(re) == -1) continue;
429 sortableColumnNumbers[sortableColumnNumbers.length] = th;
432 for(row = 0; row < numberOfRows; row++) {
435 if(tr.parentNode != start || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue;
439 for(var tmp = 0, th; th = sortableColumnNumbers[tmp]; tmp++) {
440 col = th.className.match(re)[1];
443 txt = fdTableSort.getInnerText(td) + " ";
444 txt = txt.replace(/^\s+/,'').replace(/\s+$/,'');
446 if(th.className.search(/sortable-date/) != -1) {
447 txt = fdTableSort.dateFormat(txt, th.className.search(/sortable-date-dmy/) != -1);
448 } else if(th.className.search(/sortable-numeric|sortable-currency/) != -1) {
449 txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));
450 if(isNaN(txt)) txt = "";
451 } else if(th.className.search(/sortable-text/) != -1) {
452 txt = txt.toLowerCase();
453 } else if (th.className.search(/sortable-keep/) != -1) {
455 } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1) {
456 if((th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData") in window) {
457 txt = window[th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData"](td, txt);
459 } else if(txt != "") {
460 fdTableSort.removeClass(th, "sortable");
461 if(fdTableSort.dateFormat(txt) != 0) {
462 fdTableSort.addClass(th, "sortable-date");
463 txt = fdTableSort.dateFormat(txt);
464 } else if(txt.search(fdTableSort.regExp_Number) != -1 || txt.search(fdTableSort.regExp_Currency) != -1) {
465 fdTableSort.addClass(th, "sortable-numeric");
466 txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));
467 if(isNaN(txt)) txt = "";
469 fdTableSort.addClass(th, "sortable-text");
470 txt = txt.toLowerCase();
474 if(rowCnt > 0 && identical[col] && identVal[col] != txt) { identical[col] = false; };
477 data[rowCnt][col] = txt;
479 data[rowCnt][numberOfCols] = tr;
483 var colStyle = table.className.search(/colstyle-([\S]+)/) != -1 ? table.className.match(/colstyle-([\S]+)/)[1] : false;
484 var rowStyle = table.className.search(/rowstyle-([\S]+)/) != -1 ? table.className.match(/rowstyle-([\S]+)/)[1] : false;
485 var iCBack = table.className.search(/sortinitiatedcallback-([\S-]+)/) == -1 ? "sortInitiatedCallback" : table.className.match(/sortinitiatedcallback-([\S]+)/)[1];
486 var cCBack = table.className.search(/sortcompletecallback-([\S-]+)/) == -1 ? "sortCompleteCallback" : table.className.match(/sortcompletecallback-([\S]+)/)[1];
487 iCBack = iCBack.replace("-", ".");
488 cCBack = cCBack.replace("-", ".");
489 fdTableSort.tableCache[table.id] = { hook:start, initiatedCallback:iCBack, completeCallback:cCBack, thList:[], colOrder:{}, data:data, identical:identical, colStyle:colStyle, rowStyle:rowStyle, noArrow:table.className.search(/no-arrow/) != -1 };
490 sortableColumnNumbers = data = tr = td = th = trs = identical = identVal = null;
492 onUnload: function() {
493 for(tbl in fdTableSort.tableCache) { fdTableSort.removeTableCache(tbl); };
494 for(tbl in fdTableSort.tmpCache) { fdTableSort.removeTmpCache(tbl); };
495 fdTableSort.removeEvent(window, "load", fdTableSort.initEvt);
496 fdTableSort.removeEvent(window, "unload", fdTableSort.onUnload);
497 fdTableSort.tmpCache = fdTableSort.tableCache = null;
499 addThNode: function() {
500 var dataObj = fdTableSort.tableCache[fdTableSort.tableId];
501 var pos = fdTableSort.thNode.className.match(/fd-column-([0-9]+)/)[1];
504 if(!fdTableSort.multi) {
505 if(dataObj.colStyle) {
506 var len = dataObj.thList.length;
507 for(var i = 0; i < len; i++) {
508 dataObj.colOrder[dataObj.thList[i].className.match(/fd-column-([0-9]+)/)[1]] = false;
511 if(dataObj.thList.length && dataObj.thList[0] == fdTableSort.thNode) alt = true;
516 var l = dataObj.thList.length;
518 for(var i = 0, n; n = dataObj.thList[i]; i++) {
519 if(n == fdTableSort.thNode) {
526 dataObj.thList.push(fdTableSort.thNode);
527 if(dataObj.colStyle) { dataObj.colOrder[pos] = true; };
530 var ths = document.getElementById(fdTableSort.tableId).getElementsByTagName("th");
531 for(var i = 0, th; th = ths[i]; i++) {
533 for(var z = 0, n; n = dataObj.thList[z]; z++) {
540 fdTableSort.removeClass(th, "(forwardSort|reverseSort)");
541 if(!dataObj.noArrow) {
542 span = th.getElementsByTagName('span');
545 while(span.firstChild) span.removeChild(span.firstChild);
551 if(dataObj.thList.length > 1) {
552 classToAdd = fdTableSort.thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort";
553 fdTableSort.removeClass(fdTableSort.thNode, "(forwardSort|reverseSort)");
554 fdTableSort.addClass(fdTableSort.thNode, classToAdd);
556 } else if(alt) { dataObj.pos = fdTableSort.thNode };
558 initSort: function(noCallback, ident) {
559 var thNode = fdTableSort.thNode;
560 var tableElem = document.getElementById(fdTableSort.tableId);
562 if(!(fdTableSort.tableId in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); };
564 fdTableSort.addThNode();
566 if(!noCallback) { fdTableSort.doCallback(true); };
568 fdTableSort.pos = thNode.className.match(/fd-column-([0-9]+)/)[1];
569 var dataObj = fdTableSort.tableCache[tableElem.id];
570 var lastPos = dataObj.pos && dataObj.pos.className ? dataObj.pos.className.match(/fd-column-([0-9]+)/)[1] : -1;
571 var len1 = dataObj.data.length;
572 var len2 = dataObj.data.length > 0 ? dataObj.data[0].length - 1 : 0;
573 var identical = dataObj.identical[fdTableSort.pos];
574 var classToAdd = "forwardSort";
576 if(dataObj.thList.length > 1) {
577 var js = "var sortWrapper = function(a,b) {\n";
578 var l = dataObj.thList.length;
582 for(var i=0; i < l; i++) {
583 th = dataObj.thList[i];
584 p = th.className.match(/fd-column-([0-9]+)/)[1];
585 if(dataObj.identical[p]) { continue; };
588 if(th.className.match(/sortable-(numeric|currency|date|keep)/)) {
589 f = "fdTableSort.sortNumeric";
590 } else if(th.className.match('sortable-text')) {
591 f = "fdTableSort.sortText";
592 } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && th.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) {
593 f = "window['" + th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "']";
594 } else f = "fdTableSort.sortText";
597 d = th.className.search('forwardSort') != -1 ? "a,b" : "b,a";
598 js += "fdTableSort.pos = " + p + ";\n";
599 js += "var " + e + " = "+f+"(" + d +");\n";
600 js += "if(" + e + ") return " + e + ";\n";
606 for(var i=0; i < cnt; i++) {
610 if(cnt) js += "return 0;\n";
614 dataObj.data.sort(sortWrapper);
616 } else if((lastPos == fdTableSort.pos && !identical) || (thNode.className.search(/sortable-keep/) != -1 && lastPos == -1)) {
617 dataObj.data.reverse();
618 classToAdd = thNode.className.search(/reverseSort/) != -1 ? "forwardSort" : "reverseSort";
619 if(thNode.className.search(/sortable-keep/) != -1 && lastPos == -1) fdTableSort.tableCache[tableElem.id].pos = thNode;
621 fdTableSort.tableCache[tableElem.id].pos = thNode;
622 classToAdd = thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort";
624 if(thNode.className.match(/sortable-(numeric|currency|date|keep)/)) {
625 dataObj.data.sort(fdTableSort.sortNumeric);
626 } else if(thNode.className.match('sortable-text')) {
627 dataObj.data.sort(fdTableSort.sortText);
628 } else if(thNode.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) {
629 dataObj.data.sort(window[thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1]]);
632 if(thNode.className.search(/(^|\s)favour-reverse($|\s)/) != -1) {
633 classToAdd = classToAdd == "forwardSort" ? "reverseSort" : "forwardSort";
634 dataObj.data.reverse();
638 if(ident) { identical = false; };
639 if(dataObj.thList.length == 1) {
640 fdTableSort.removeClass(thNode, "(forwardSort|reverseSort)");
641 fdTableSort.addClass(thNode, classToAdd);
643 if(!dataObj.noArrow) {
644 var span = fdTableSort.thNode.getElementsByTagName('span')[0];
645 if(span.firstChild) span.removeChild(span.firstChild);
646 span.appendChild(document.createTextNode(fdTableSort.thNode.className.search(/forwardSort/) != -1 ? " \u2193" : " \u2191"));
648 if(!dataObj.rowStyle && !dataObj.colStyle && identical) {
649 fdTableSort.removeSortActiveClass();
650 if(!noCallback) { fdTableSort.doCallback(false); };
651 fdTableSort.thNode = null;
654 if("tablePaginater" in window && tablePaginater.tableIsPaginated(fdTableSort.tableId)) {
655 tablePaginater.redraw(fdTableSort.tableId, identical);
657 fdTableSort.redraw(fdTableSort.tableId, identical);
659 fdTableSort.removeSortActiveClass();
660 if(!noCallback) { fdTableSort.doCallback(false); };
661 fdTableSort.thNode = null;
663 redraw: function(tableid, identical) {
664 if (debug) plc_message ('entering tablesort.redraw');
665 if(!tableid || !(tableid in fdTableSort.tableCache)) { return; };
666 var dataObj = fdTableSort.tableCache[tableid];
667 var data = dataObj.data;
668 var len1 = data.length;
669 var len2 = len1 ? data[0].length - 1 : 0;
670 var hook = dataObj.hook;
671 var colStyle = dataObj.colStyle;
672 var rowStyle = dataObj.rowStyle;
673 var colOrder = dataObj.colOrder;
675 var reg = /(^|\s)invisibleRow(\s|$)/;
678 for(var i = 0; i < len1; i++) {
682 for(thPos in colOrder) {
683 if(!colOrder[thPos]) fdTableSort.removeClass(tds[thPos], colStyle);
684 else fdTableSort.addClass(tds[thPos], colStyle);
688 if(rowStyle && tr.className.search(reg) == -1) {
689 if(highLight++ & 1) fdTableSort.addClass(tr, rowStyle);
690 else fdTableSort.removeClass(tr, rowStyle);
693 // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser
694 // hook.removeChild(tr);
695 hook.appendChild(tr);
698 tr = tds = hook = null;
699 if (debug) plc_message ('exiting tablesort.redraw');
701 getInnerText: function(el, allowBrTags) {
702 if (typeof el == "string" || typeof el == "undefined") return el;
703 if(el.innerText) return el.innerText;
705 for(i = el.firstChild; i; i = i.nextSibling) {
706 if(allowBrTags && i.nodeName && i.nodeName == "BR") txt += "<br />";
707 else if(i.nodeType == 3) txt += i.nodeValue;
708 else if(i.nodeType == 1) txt += fdTableSort.getInnerText(i);
712 dateFormat: function(dateIn, favourDMY) {
714 { regExp:/^(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])([- \/.])((\d\d)?\d\d)$/, d:3, m:1, y:5 }, // mdy
715 { regExp:/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/, d:1, m:3, y:5 }, // dmy
716 { regExp:/^(\d\d\d\d)([- \/.])(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])$/, d:5, m:3, y:1 } // ymd
718 var start, cnt = 0, numFormats = dateTest.length;
719 while(cnt < numFormats) {
720 start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats;
721 if(dateIn.match(dateTest[start].regExp)) {
722 res = dateIn.match(dateTest[start].regExp);
723 y = res[dateTest[start].y];
724 m = res[dateTest[start].m];
725 d = res[dateTest[start].d];
726 if(m.length == 1) m = "0" + String(m);
727 if(d.length == 1) d = "0" + String(d);
728 if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y);
730 return y+String(m)+d;
736 sortNumeric:function(a,b) {
737 var aa = a[fdTableSort.pos];
738 var bb = b[fdTableSort.pos];
739 if(aa == bb) return 0;
740 if(aa === "" && !isNaN(bb)) return -1;
741 if(bb === "" && !isNaN(aa)) return 1;
744 sortText:function(a,b) {
745 var aa = a[fdTableSort.pos];
746 var bb = b[fdTableSort.pos];
747 if(aa == bb) return 0;
748 if(aa < bb) return -1;
753 fdTableSort.addEvent(window, "load", fdTableSort.initEvt);
754 fdTableSort.addEvent(window, "unload", fdTableSort.onUnload);