2 TableSort revisited v5.0 by frequency-decoder.com
\r
4 Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/)
\r
6 Please credit frequency decoder in any derivative work - thanks
\r
10 * to copy, distribute, display, and perform the work
\r
11 * to make derivative works
\r
12 * to make commercial use of the work
\r
14 Under the following conditions:
\r
18 You must attribute the work in the manner specified by the author or licensor.
\r
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.
\r
24 * For any reuse or distribution, you must make clear to others the license terms of this work.
\r
25 * Any of these conditions can be waived if you get permission from the copyright holder.
\r
30 regExp_Currency: /^[£$€¥¤]/,
\r
31 regExp_Number: /^(\-)?[0-9]+(\.[0-9]*)?$/,
\r
38 sortActiveClass: "sort-active",
\r
49 addEvent: function(obj, type, fn, tmp) {
\r
50 tmp || (tmp = true);
\r
51 if( obj.attachEvent ) {
\r
52 obj["e"+type+fn] = fn;
\r
53 obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
\r
54 obj.attachEvent( "on"+type, obj[type+fn] );
\r
56 obj.addEventListener( type, fn, true );
\r
59 removeEvent: function(obj, type, fn, tmp) {
\r
60 tmp || (tmp = true);
\r
62 if( obj.detachEvent ) {
\r
63 obj.detachEvent( "on"+type, obj[type+fn] );
\r
64 obj[type+fn] = null;
\r
66 obj.removeEventListener( type, fn, true );
\r
70 stopEvent: function(e) {
\r
71 e = e || window.event;
\r
73 if(e.stopPropagation) {
\r
74 e.stopPropagation();
\r
80 e.cancelBubble = true;
\r
81 e.returnValue = false;
\r
85 parseClassName: function(head, tbl) {
\r
86 var colMatch = tbl.className.match(new RegExp(head + "((-[\\d]+([r]){0,1})+)"));
\r
87 return colMatch && colMatch.length ? colMatch[0].replace(head, "").split("-") : [];
\r
89 disableSelection: function(element) {
\r
90 element.onselectstart = function() {
\r
93 element.unselectable = "on";
\r
94 element.style.MozUserSelect = "none";
\r
96 removeTableCache: function(tableId) {
\r
97 if(!(tableId in fdTableSort.tableCache)) return;
\r
99 fdTableSort.tableCache[tableId] = null;
\r
100 delete fdTableSort.tableCache[tableId];
\r
102 var tbl = document.getElementById(tableId);
\r
104 var ths = tbl.getElementsByTagName("th");
\r
106 for(var i = 0, th; th = ths[i]; i++) {
\r
107 a = th.getElementsByTagName("a");
\r
108 if(a.length) a[0].onkeydown = a[0].onclick = null;
\r
109 th.onclick = th.onselectstart = th = a = null;
\r
112 removeTmpCache: function(tableId) {
\r
113 if(!(tableId in fdTableSort.tmpCache)) return;
\r
114 var headers = fdTableSort.tmpCache[tableId].headers;
\r
116 for(var i = 0, row; row = headers[i]; i++) {
\r
117 for(var j = 0, th; th = row[j]; j++) {
\r
118 a = th.getElementsByTagName("a");
\r
119 if(a.length) a[0].onkeydown = a[0].onclick = null;
\r
120 th.onclick = th.onselectstart = th = a = null;
\r
123 fdTableSort.tmpCache[tableId] = null;
\r
124 delete fdTableSort.tmpCache[tableId];
\r
126 initEvt: function(e) {
\r
127 fdTableSort.init(false);
\r
129 init: function(tableId) {
\r
130 if (!document.getElementsByTagName || !document.createElement || !document.getElementById) return;
\r
132 var tables = tableId && document.getElementById(tableId) ? [document.getElementById(tableId)] : document.getElementsByTagName("table");
\r
133 var c, ii, len, colMatch, showOnly, match, showArrow, columnNumSortObj, obj, workArr, headers, thtext, aclone, multi, colCnt, cel, allRowArr, rowArr, sortableTable, celCount, colspan, rowspan, rowLength;
\r
135 var a = document.createElement("a");
\r
137 a.className = "fdTableSortTrigger";
\r
139 var span = document.createElement("span");
\r
141 for(var k = 0, tbl; tbl = tables[k]; k++) {
\r
144 fdTableSort.removeTableCache(tbl.id);
\r
145 fdTableSort.removeTmpCache(tbl.id);
\r
148 allRowArr = tbl.getElementsByTagName('thead').length ? tbl.getElementsByTagName('thead')[0].getElementsByTagName('tr') : tbl.getElementsByTagName('tr');
\r
150 sortableTable = false;
\r
152 for(var i = 0, tr; tr = allRowArr[i]; i++) {
\r
153 if(tr.getElementsByTagName('td').length || !tr.getElementsByTagName('th').length) { continue; };
\r
154 rowArr[rowArr.length] = tr.getElementsByTagName('th');
\r
155 for(var j = 0, th; th = rowArr[rowArr.length - 1][j]; j++) {
\r
156 if(th.className.search(/sortable/) != -1) { sortableTable = true; };
\r
160 if(!sortableTable) continue;
\r
162 if(!tbl.id) { tbl.id = "fd-table-" + fdTableSort.uniqueHash++; };
\r
164 showArrow = tbl.className.search("no-arrow") == -1;
\r
165 showOnly = tbl.className.search("sortable-onload-show") != -1;
\r
167 columnNumSortObj = {};
\r
168 colMatch = fdTableSort.parseClassName(showOnly ? "sortable-onload-show" : "sortable-onload", tbl);
\r
169 for(match = 1; match < colMatch.length; match++) {
\r
170 columnNumSortObj[parseInt(colMatch[match], 10)] = { "reverse":colMatch[match].search("r") != -1 };
\r
173 rowLength = rowArr[0].length;
\r
175 for(c = 0;c < rowArr[0].length;c++){
\r
176 if(rowArr[0][c].getAttribute(fdTableSort.colspan) && rowArr[0][c].getAttribute(fdTableSort.colspan) > 1){
\r
177 rowLength = rowLength + (rowArr[0][c].getAttribute(fdTableSort.colspan) - 1);
\r
181 workArr = new Array(rowArr.length);
\r
182 for(c = rowArr.length;c--;){ workArr[c]= new Array(rowLength); };
\r
184 for(c = 0;c < workArr.length;c++){
\r
186 for(i = 0;i < rowLength;i++){
\r
187 if(!workArr[c][i]){
\r
188 cel = rowArr[c][celCount];
\r
189 colspan = (cel.getAttribute(fdTableSort.colspan) > 1) ? cel.getAttribute(fdTableSort.colspan):1;
\r
190 rowspan = (cel.getAttribute(fdTableSort.rowspan) > 1) ? cel.getAttribute(fdTableSort.rowspan):1;
\r
191 for(var t = 0;((t < colspan)&&((i+t) < rowLength));t++){
\r
192 for(var n = 0;((n < rowspan)&&((c+n) < workArr.length));n++) {
\r
193 workArr[(c+n)][(i+t)] = cel;
\r
196 if(++celCount == rowArr[c].length) break;
\r
201 for(c = 0;c < workArr.length;c++) {
\r
202 for(i = 0;i < workArr[c].length;i++){
\r
204 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;
\r
206 if(workArr[c][i].className.match('sortable')) {
\r
207 workArr[c][i].className = workArr[c][i].className.replace(/forwardSort|reverseSort/, "");
\r
209 if(i in columnNumSortObj) {
\r
210 columnNumSortObj[i]["thNode"] = workArr[c][i];
\r
211 columnNumSortObj["active"] = true;
\r
214 thtext = fdTableSort.getInnerText(workArr[c][i], true);
\r
216 for(var cn = workArr[c][i].childNodes.length; cn--;) {
\r
217 // Skip image nodes and links created by the filter script.
\r
218 if(workArr[c][i].childNodes[cn].nodeType == 1 && (workArr[c][i].childNodes[cn].className == "fdFilterTrigger" || /img/i.test(workArr[c][i].childNodes[cn].nodeName))) {
\r
221 if(workArr[c][i].childNodes[cn].nodeType == 1 && /^a$/i.test(workArr[c][i].childNodes[cn].nodeName)) {
\r
222 workArr[c][i].childNodes[cn].onclick = workArr[c][i].childNodes[cn].onkeydown = null;
\r
224 workArr[c][i].removeChild(workArr[c][i].childNodes[cn]);
\r
227 aclone = a.cloneNode(true);
\r
228 //aclone.appendChild(document.createTextNode(thtext));
\r
229 aclone.innerHTML = thtext;
\r
230 aclone.title = "Sort on \u201c" + thtext.replace('<br />', '') + "\u201d";
\r
231 aclone.onclick = aclone.onkeydown = workArr[c][i].onclick = fdTableSort.initWrapper;
\r
232 workArr[c][i].appendChild(aclone);
\r
233 if(showArrow) workArr[c][i].appendChild(span.cloneNode(false));
\r
234 workArr[c][i].className = workArr[c][i].className.replace(/fd-identical|fd-not-identical/, "");
\r
235 fdTableSort.disableSelection(workArr[c][i]);
\r
241 fdTableSort.tmpCache[tbl.id] = {cols:rowLength, headers:workArr};
\r
246 if("active" in columnNumSortObj) {
\r
247 fdTableSort.tableId = tbl.id;
\r
248 fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId));
\r
250 delete columnNumSortObj["active"];
\r
252 for(col in columnNumSortObj) {
\r
253 obj = columnNumSortObj[col];
\r
254 if(!("thNode" in obj)) { continue; };
\r
255 fdTableSort.multi = true;
\r
257 len = obj.reverse ? 2 : 1;
\r
259 for(ii = 0; ii < len; ii++) {
\r
260 fdTableSort.thNode = obj.thNode;
\r
262 fdTableSort.initSort(false, true);
\r
264 fdTableSort.addThNode();
\r
269 fdTableSort.removeClass(obj.thNode, "(forwardSort|reverseSort)");
\r
270 fdTableSort.addClass(obj.thNode, obj.reverse ? "reverseSort" : "forwardSort");
\r
272 span = fdTableSort.thNode.getElementsByTagName('span')[0];
\r
273 if(span.firstChild) { span.removeChild(span.firstChild); };
\r
274 span.appendChild(document.createTextNode(len == 1 ? " \u2193" : " \u2191"));
\r
278 if(showOnly && (fdTableSort.tableCache[tbl.id].colStyle || fdTableSort.tableCache[tbl.id].rowStyle)) {
\r
279 fdTableSort.redraw(tbl.id, false);
\r
281 } else if(tbl.className.search(/onload-zebra/) != -1) {
\r
282 fdTableSort.tableId = tbl.id;
\r
283 fdTableSort.prepareTableData(tbl);
\r
284 if(fdTableSort.tableCache[tbl.id].rowStyle) { fdTableSort.redraw(tbl.id, false); };
\r
288 fdTableSort.thNode = aclone = a = span = columnNumSortObj = thNode = tbl = allRowArr = rowArr = null;
\r
290 initWrapper: function(e) {
\r
291 e = e || window.event;
\r
292 var kc = e.type == "keydown" ? e.keyCode != null ? e.keyCode : e.charCode : -1;
\r
293 if(fdTableSort.thNode == null && (e.type == "click" || kc == 13)) {
\r
295 while(targ.tagName.toLowerCase() != "th") { targ = targ.parentNode; };
\r
296 fdTableSort.thNode = targ;
\r
297 while(targ.tagName.toLowerCase() != "table") { targ = targ.parentNode; };
\r
298 fdTableSort.tableId = targ.id;
\r
299 fdTableSort.multi = e.shiftKey;
\r
300 fdTableSort.addSortActiveClass();
\r
301 setTimeout(fdTableSort.initSort,5,false);
\r
302 return fdTableSort.stopEvent(e);
\r
304 return kc != -1 ? true : fdTableSort.stopEvent(e);
\r
306 jsWrapper: function(tableid, colNums) {
\r
307 if(!(tableid in fdTableSort.tmpCache)) { return false; };
\r
308 if(!(tableid in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(tableid)); };
\r
309 if(!(colNums instanceof Array)) { colNums = [colNums]; };
\r
311 fdTableSort.tableId = tableid;
\r
312 var len = colNums.length, colNum;
\r
314 if(fdTableSort.tableCache[tableid].thList.length == colNums.length) {
\r
315 var identical = true;
\r
317 for(var i = 0; i < len; i++) {
\r
318 colNum = colNums[i];
\r
319 th = fdTableSort.tmpCache[tableid].headers[0][colNum];
\r
320 if(th != fdTableSort.tableCache[tableid].thList[i]) {
\r
326 fdTableSort.thNode = th;
\r
327 fdTableSort.initSort(true);
\r
332 fdTableSort.addSortActiveClass();
\r
334 for(var i = 0; i < len; i++) {
\r
335 fdTableSort.multi = i;
\r
336 colNum = colNums[i];
\r
337 fdTableSort.thNode = fdTableSort.tmpCache[tableid].headers[0][colNum];
\r
338 fdTableSort.initSort(true);
\r
341 addSortActiveClass: function() {
\r
342 if(fdTableSort.thNode == null) { return; };
\r
343 fdTableSort.addClass(fdTableSort.thNode, fdTableSort.sortActiveClass);
\r
344 fdTableSort.addClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass);
\r
346 removeSortActiveClass: function() {
\r
347 if(fdTableSort.thNode == null) return;
\r
348 fdTableSort.removeClass(fdTableSort.thNode, fdTableSort.sortActiveClass);
\r
349 fdTableSort.removeClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass);
\r
351 doCallback: function(init) {
\r
352 if(!fdTableSort.tableId || !(fdTableSort.tableId in fdTableSort.tableCache)) { return; };
\r
353 fdTableSort.callback(fdTableSort.tableId, init ? fdTableSort.tableCache[fdTableSort.tableId].initiatedCallback : fdTableSort.tableCache[fdTableSort.tableId].completeCallback);
\r
355 addClass: function(e,c) {
\r
356 if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) { return; };
\r
357 e.className += ( e.className ? " " : "" ) + c;
\r
361 removeClass: function(e,c) {
\r
362 e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1');
\r
365 removeClass: function(e,c) {
\r
366 e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
\r
370 callback: function(tblId, cb) {
\r
373 if(cb.indexOf(".") != -1) {
\r
374 parts = cb.split('.');
\r
376 for (var x = 0, part; part = obj[parts[x]]; x++) {
\r
377 if(part instanceof Function) {
\r
380 func = function (data) { method.apply(obj, [data]) };
\r
386 } else if(cb + tblId in window) {
\r
387 func = window[cb + tblId];
\r
388 } else if(cb in window) {
\r
395 if(!(func instanceof Function)) return;
\r
396 func(tblId, fdTableSort.tableCache[tblId].thList);
\r
398 prepareTableData: function(table) {
\r
401 var start = table.getElementsByTagName('tbody');
\r
402 start = start.length ? start[0] : table;
\r
404 var trs = start.rows;
\r
405 var ths = table.getElementsByTagName('th');
\r
407 var numberOfRows = trs.length;
\r
408 var numberOfCols = fdTableSort.tmpCache[table.id].cols;
\r
411 var identical = new Array(numberOfCols);
\r
412 var identVal = new Array(numberOfCols);
\r
414 for(var tmp = 0; tmp < numberOfCols; tmp++) identical[tmp] = true;
\r
416 var tr, td, th, txt, tds, col, row;
\r
418 var re = new RegExp(/fd-column-([0-9]+)/);
\r
421 var sortableColumnNumbers = [];
\r
423 for(var tmp = 0, th; th = ths[tmp]; tmp++) {
\r
424 if(th.className.search(re) == -1) continue;
\r
425 sortableColumnNumbers[sortableColumnNumbers.length] = th;
\r
428 for(row = 0; row < numberOfRows; row++) {
\r
431 if(tr.parentNode != start || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue;
\r
435 for(var tmp = 0, th; th = sortableColumnNumbers[tmp]; tmp++) {
\r
436 col = th.className.match(re)[1];
\r
439 txt = fdTableSort.getInnerText(td) + " ";
\r
440 txt = txt.replace(/^\s+/,'').replace(/\s+$/,'');
\r
442 if(th.className.search(/sortable-date/) != -1) {
\r
443 txt = fdTableSort.dateFormat(txt, th.className.search(/sortable-date-dmy/) != -1);
\r
444 } else if(th.className.search(/sortable-numeric|sortable-currency/) != -1) {
\r
445 txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));
\r
446 if(isNaN(txt)) txt = "";
\r
447 } else if(th.className.search(/sortable-text/) != -1) {
\r
448 txt = txt.toLowerCase();
\r
449 } else if (th.className.search(/sortable-keep/) != -1) {
\r
451 } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1) {
\r
452 if((th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData") in window) {
\r
453 txt = window[th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData"](td, txt);
\r
455 } else if(txt != "") {
\r
456 fdTableSort.removeClass(th, "sortable");
\r
457 if(fdTableSort.dateFormat(txt) != 0) {
\r
458 fdTableSort.addClass(th, "sortable-date");
\r
459 txt = fdTableSort.dateFormat(txt);
\r
460 } else if(txt.search(fdTableSort.regExp_Number) != -1 || txt.search(fdTableSort.regExp_Currency) != -1) {
\r
461 fdTableSort.addClass(th, "sortable-numeric");
\r
462 txt = parseFloat(txt.replace(/[^0-9\.\-]/g,''));
\r
463 if(isNaN(txt)) txt = "";
\r
465 fdTableSort.addClass(th, "sortable-text");
\r
466 txt = txt.toLowerCase();
\r
470 if(rowCnt > 0 && identical[col] && identVal[col] != txt) { identical[col] = false; };
\r
472 identVal[col] = txt;
\r
473 data[rowCnt][col] = txt;
\r
475 data[rowCnt][numberOfCols] = tr;
\r
479 var colStyle = table.className.search(/colstyle-([\S]+)/) != -1 ? table.className.match(/colstyle-([\S]+)/)[1] : false;
\r
480 var rowStyle = table.className.search(/rowstyle-([\S]+)/) != -1 ? table.className.match(/rowstyle-([\S]+)/)[1] : false;
\r
481 var iCBack = table.className.search(/sortinitiatedcallback-([\S-]+)/) == -1 ? "sortInitiatedCallback" : table.className.match(/sortinitiatedcallback-([\S]+)/)[1];
\r
482 var cCBack = table.className.search(/sortcompletecallback-([\S-]+)/) == -1 ? "sortCompleteCallback" : table.className.match(/sortcompletecallback-([\S]+)/)[1];
\r
483 iCBack = iCBack.replace("-", ".");
\r
484 cCBack = cCBack.replace("-", ".");
\r
485 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 };
\r
486 sortableColumnNumbers = data = tr = td = th = trs = identical = identVal = null;
\r
488 onUnload: function() {
\r
489 for(tbl in fdTableSort.tableCache) { fdTableSort.removeTableCache(tbl); };
\r
490 for(tbl in fdTableSort.tmpCache) { fdTableSort.removeTmpCache(tbl); };
\r
491 fdTableSort.removeEvent(window, "load", fdTableSort.initEvt);
\r
492 fdTableSort.removeEvent(window, "unload", fdTableSort.onUnload);
\r
493 fdTableSort.tmpCache = fdTableSort.tableCache = null;
\r
495 addThNode: function() {
\r
496 var dataObj = fdTableSort.tableCache[fdTableSort.tableId];
\r
497 var pos = fdTableSort.thNode.className.match(/fd-column-([0-9]+)/)[1];
\r
500 if(!fdTableSort.multi) {
\r
501 if(dataObj.colStyle) {
\r
502 var len = dataObj.thList.length;
\r
503 for(var i = 0; i < len; i++) {
\r
504 dataObj.colOrder[dataObj.thList[i].className.match(/fd-column-([0-9]+)/)[1]] = false;
\r
507 if(dataObj.thList.length && dataObj.thList[0] == fdTableSort.thNode) alt = true;
\r
508 dataObj.thList = [];
\r
512 var l = dataObj.thList.length;
\r
514 for(var i = 0, n; n = dataObj.thList[i]; i++) {
\r
515 if(n == fdTableSort.thNode) {
\r
522 dataObj.thList.push(fdTableSort.thNode);
\r
523 if(dataObj.colStyle) { dataObj.colOrder[pos] = true; };
\r
526 var ths = document.getElementById(fdTableSort.tableId).getElementsByTagName("th");
\r
527 for(var i = 0, th; th = ths[i]; i++) {
\r
529 for(var z = 0, n; n = dataObj.thList[z]; z++) {
\r
536 fdTableSort.removeClass(th, "(forwardSort|reverseSort)");
\r
537 if(!dataObj.noArrow) {
\r
538 span = th.getElementsByTagName('span');
\r
541 while(span.firstChild) span.removeChild(span.firstChild);
\r
547 if(dataObj.thList.length > 1) {
\r
548 classToAdd = fdTableSort.thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort";
\r
549 fdTableSort.removeClass(fdTableSort.thNode, "(forwardSort|reverseSort)");
\r
550 fdTableSort.addClass(fdTableSort.thNode, classToAdd);
\r
552 } else if(alt) { dataObj.pos = fdTableSort.thNode };
\r
554 initSort: function(noCallback, ident) {
\r
555 var thNode = fdTableSort.thNode;
\r
556 var tableElem = document.getElementById(fdTableSort.tableId);
\r
558 if(!(fdTableSort.tableId in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); };
\r
560 fdTableSort.addThNode();
\r
562 if(!noCallback) { fdTableSort.doCallback(true); };
\r
564 fdTableSort.pos = thNode.className.match(/fd-column-([0-9]+)/)[1];
\r
565 var dataObj = fdTableSort.tableCache[tableElem.id];
\r
566 var lastPos = dataObj.pos && dataObj.pos.className ? dataObj.pos.className.match(/fd-column-([0-9]+)/)[1] : -1;
\r
567 var len1 = dataObj.data.length;
\r
568 var len2 = dataObj.data.length > 0 ? dataObj.data[0].length - 1 : 0;
\r
569 var identical = dataObj.identical[fdTableSort.pos];
\r
570 var classToAdd = "forwardSort";
\r
572 if(dataObj.thList.length > 1) {
\r
573 var js = "var sortWrapper = function(a,b) {\n";
\r
574 var l = dataObj.thList.length;
\r
578 for(var i=0; i < l; i++) {
\r
579 th = dataObj.thList[i];
\r
580 p = th.className.match(/fd-column-([0-9]+)/)[1];
\r
581 if(dataObj.identical[p]) { continue; };
\r
584 if(th.className.match(/sortable-(numeric|currency|date|keep)/)) {
\r
585 f = "fdTableSort.sortNumeric";
\r
586 } else if(th.className.match('sortable-text')) {
\r
587 f = "fdTableSort.sortText";
\r
588 } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && th.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) {
\r
589 f = "window['" + th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "']";
\r
590 } else f = "fdTableSort.sortText";
\r
593 d = th.className.search('forwardSort') != -1 ? "a,b" : "b,a";
\r
594 js += "fdTableSort.pos = " + p + ";\n";
\r
595 js += "var " + e + " = "+f+"(" + d +");\n";
\r
596 js += "if(" + e + ") return " + e + ";\n";
\r
600 js += "return 0;\n";
\r
602 for(var i=0; i < cnt; i++) {
\r
606 if(cnt) js += "return 0;\n";
\r
610 dataObj.data.sort(sortWrapper);
\r
612 } else if((lastPos == fdTableSort.pos && !identical) || (thNode.className.search(/sortable-keep/) != -1 && lastPos == -1)) {
\r
613 dataObj.data.reverse();
\r
614 classToAdd = thNode.className.search(/reverseSort/) != -1 ? "forwardSort" : "reverseSort";
\r
615 if(thNode.className.search(/sortable-keep/) != -1 && lastPos == -1) fdTableSort.tableCache[tableElem.id].pos = thNode;
\r
617 fdTableSort.tableCache[tableElem.id].pos = thNode;
\r
618 classToAdd = thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort";
\r
620 if(thNode.className.match(/sortable-(numeric|currency|date|keep)/)) {
\r
621 dataObj.data.sort(fdTableSort.sortNumeric);
\r
622 } else if(thNode.className.match('sortable-text')) {
\r
623 dataObj.data.sort(fdTableSort.sortText);
\r
624 } else if(thNode.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) {
\r
625 dataObj.data.sort(window[thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1]]);
\r
628 if(thNode.className.search(/(^|\s)favour-reverse($|\s)/) != -1) {
\r
629 classToAdd = classToAdd == "forwardSort" ? "reverseSort" : "forwardSort";
\r
630 dataObj.data.reverse();
\r
634 if(ident) { identical = false; };
\r
635 if(dataObj.thList.length == 1) {
\r
636 fdTableSort.removeClass(thNode, "(forwardSort|reverseSort)");
\r
637 fdTableSort.addClass(thNode, classToAdd);
\r
639 if(!dataObj.noArrow) {
\r
640 var span = fdTableSort.thNode.getElementsByTagName('span')[0];
\r
641 if(span.firstChild) span.removeChild(span.firstChild);
\r
642 span.appendChild(document.createTextNode(fdTableSort.thNode.className.search(/forwardSort/) != -1 ? " \u2193" : " \u2191"));
\r
644 if(!dataObj.rowStyle && !dataObj.colStyle && identical) {
\r
645 fdTableSort.removeSortActiveClass();
\r
646 if(!noCallback) { fdTableSort.doCallback(false); };
\r
647 fdTableSort.thNode = null;
\r
650 if("tablePaginater" in window && tablePaginater.tableIsPaginated(fdTableSort.tableId)) {
\r
651 tablePaginater.redraw(fdTableSort.tableId, identical);
\r
653 fdTableSort.redraw(fdTableSort.tableId, identical);
\r
655 fdTableSort.removeSortActiveClass();
\r
656 if(!noCallback) { fdTableSort.doCallback(false); };
\r
657 fdTableSort.thNode = null;
\r
659 redraw: function(tableid, identical) {
\r
660 if(!tableid || !(tableid in fdTableSort.tableCache)) { return; };
\r
661 var dataObj = fdTableSort.tableCache[tableid];
\r
662 var data = dataObj.data;
\r
663 var len1 = data.length;
\r
664 var len2 = len1 ? data[0].length - 1 : 0;
\r
665 var hook = dataObj.hook;
\r
666 var colStyle = dataObj.colStyle;
\r
667 var rowStyle = dataObj.rowStyle;
\r
668 var colOrder = dataObj.colOrder;
\r
670 var reg = /(^|\s)invisibleRow(\s|$)/;
\r
673 for(var i = 0; i < len1; i++) {
\r
674 tr = data[i][len2];
\r
677 for(thPos in colOrder) {
\r
678 if(!colOrder[thPos]) fdTableSort.removeClass(tds[thPos], colStyle);
\r
679 else fdTableSort.addClass(tds[thPos], colStyle);
\r
683 if(rowStyle && tr.className.search(reg) == -1) {
\r
684 if(highLight++ & 1) fdTableSort.addClass(tr, rowStyle);
\r
685 else fdTableSort.removeClass(tr, rowStyle);
\r
688 // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser
\r
689 // hook.removeChild(tr);
\r
690 hook.appendChild(tr);
\r
693 tr = tds = hook = null;
\r
695 getInnerText: function(el, allowBrTags) {
\r
696 if (typeof el == "string" || typeof el == "undefined") return el;
\r
697 if(el.innerText) return el.innerText;
\r
699 for(i = el.firstChild; i; i = i.nextSibling) {
\r
700 if(allowBrTags && i.nodeName && i.nodeName == "BR") txt += "<br />";
\r
701 else if(i.nodeType == 3) txt += i.nodeValue;
\r
702 else if(i.nodeType == 1) txt += fdTableSort.getInnerText(i);
\r
706 dateFormat: function(dateIn, favourDMY) {
\r
708 { 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
\r
709 { 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
\r
710 { 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
\r
712 var start, cnt = 0, numFormats = dateTest.length;
\r
713 while(cnt < numFormats) {
\r
714 start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats;
\r
715 if(dateIn.match(dateTest[start].regExp)) {
\r
716 res = dateIn.match(dateTest[start].regExp);
\r
717 y = res[dateTest[start].y];
\r
718 m = res[dateTest[start].m];
\r
719 d = res[dateTest[start].d];
\r
720 if(m.length == 1) m = "0" + String(m);
\r
721 if(d.length == 1) d = "0" + String(d);
\r
722 if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y);
\r
724 return y+String(m)+d;
\r
730 sortNumeric:function(a,b) {
\r
731 var aa = a[fdTableSort.pos];
\r
732 var bb = b[fdTableSort.pos];
\r
733 if(aa == bb) return 0;
\r
734 if(aa === "" && !isNaN(bb)) return -1;
\r
735 if(bb === "" && !isNaN(aa)) return 1;
\r
738 sortText:function(a,b) {
\r
739 var aa = a[fdTableSort.pos];
\r
740 var bb = b[fdTableSort.pos];
\r
741 if(aa == bb) return 0;
\r
742 if(aa < bb) return -1;
\r
747 fdTableSort.addEvent(window, "load", fdTableSort.initEvt);
\r
748 fdTableSort.addEvent(window, "unload", fdTableSort.onUnload);
\r