X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=plekit%2Ftablesort%2Ftablesort.js;h=9b55e595fbd68668ab7f40d3baa00897531f1a47;hb=adfd75f0d83b047e2a3c1494cbbe0c492e10886c;hp=27e8c3c4f102fe1fee4c6e1f8282157185c48ff6;hpb=89b3b635298a23b0f62430cfb189882e248ab2fb;p=plewww.git diff --git a/plekit/tablesort/tablesort.js b/plekit/tablesort/tablesort.js index 27e8c3c..9b55e59 100644 --- a/plekit/tablesort/tablesort.js +++ b/plekit/tablesort/tablesort.js @@ -1,748 +1,748 @@ -/* - TableSort revisited v5.0 by frequency-decoder.com - - Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/) - - Please credit frequency decoder in any derivative work - thanks - - You are free: - - * to copy, distribute, display, and perform the work - * to make derivative works - * to make commercial use of the work - - Under the following conditions: - - by Attribution. - -------------- - You must attribute the work in the manner specified by the author or licensor. - - sa - -- - 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. - - * For any reuse or distribution, you must make clear to others the license terms of this work. - * Any of these conditions can be waived if you get permission from the copyright holder. -*/ - -(function() { -fdTableSort = { - regExp_Currency: /^[£$€¥¤]/, - regExp_Number: /^(\-)?[0-9]+(\.[0-9]*)?$/, - pos: -1, - uniqueHash: 1, - thNode: null, - tableId: null, - tableCache: {}, - tmpCache: {}, - sortActiveClass: "sort-active", - /*@cc_on - /*@if (@_win32) - colspan: "colSpan", - rowspan: "rowSpan", - @else @*/ - colspan: "colspan", - rowspan: "rowspan", - /*@end - @*/ - - addEvent: function(obj, type, fn, tmp) { - tmp || (tmp = true); - if( obj.attachEvent ) { - obj["e"+type+fn] = fn; - obj[type+fn] = function(){obj["e"+type+fn]( window.event );}; - obj.attachEvent( "on"+type, obj[type+fn] ); - } else { - obj.addEventListener( type, fn, true ); - }; - }, - removeEvent: function(obj, type, fn, tmp) { - tmp || (tmp = true); - try { - if( obj.detachEvent ) { - obj.detachEvent( "on"+type, obj[type+fn] ); - obj[type+fn] = null; - } else { - obj.removeEventListener( type, fn, true ); - }; - } catch(err) {}; - }, - stopEvent: function(e) { - e = e || window.event; - - if(e.stopPropagation) { - e.stopPropagation(); - e.preventDefault(); - }; - - /*@cc_on@*/ - /*@if(@_win32) - e.cancelBubble = true; - e.returnValue = false; - /*@end@*/ - return false; - }, - parseClassName: function(head, tbl) { - var colMatch = tbl.className.match(new RegExp(head + "((-[\\d]+([r]){0,1})+)")); - return colMatch && colMatch.length ? colMatch[0].replace(head, "").split("-") : []; - }, - disableSelection: function(element) { - element.onselectstart = function() { - return false; - }; - element.unselectable = "on"; - element.style.MozUserSelect = "none"; - }, - removeTableCache: function(tableId) { - if(!(tableId in fdTableSort.tableCache)) return; - - fdTableSort.tableCache[tableId] = null; - delete fdTableSort.tableCache[tableId]; - - var tbl = document.getElementById(tableId); - if(!tbl) return; - var ths = tbl.getElementsByTagName("th"); - var a; - for(var i = 0, th; th = ths[i]; i++) { - a = th.getElementsByTagName("a"); - if(a.length) a[0].onkeydown = a[0].onclick = null; - th.onclick = th.onselectstart = th = a = null; - }; - }, - removeTmpCache: function(tableId) { - if(!(tableId in fdTableSort.tmpCache)) return; - var headers = fdTableSort.tmpCache[tableId].headers; - var a; - for(var i = 0, row; row = headers[i]; i++) { - for(var j = 0, th; th = row[j]; j++) { - a = th.getElementsByTagName("a"); - if(a.length) a[0].onkeydown = a[0].onclick = null; - th.onclick = th.onselectstart = th = a = null; - }; - }; - fdTableSort.tmpCache[tableId] = null; - delete fdTableSort.tmpCache[tableId]; - }, - initEvt: function(e) { - fdTableSort.init(false); - }, - init: function(tableId) { - if (!document.getElementsByTagName || !document.createElement || !document.getElementById) return; - - var tables = tableId && document.getElementById(tableId) ? [document.getElementById(tableId)] : document.getElementsByTagName("table"); - var c, ii, len, colMatch, showOnly, match, showArrow, columnNumSortObj, obj, workArr, headers, thtext, aclone, multi, colCnt, cel, allRowArr, rowArr, sortableTable, celCount, colspan, rowspan, rowLength; - - var a = document.createElement("a"); - a.href = "#"; - a.className = "fdTableSortTrigger"; - - var span = document.createElement("span"); - - for(var k = 0, tbl; tbl = tables[k]; k++) { - - if(tbl.id) { - fdTableSort.removeTableCache(tbl.id); - fdTableSort.removeTmpCache(tbl.id); - }; - - allRowArr = tbl.getElementsByTagName('thead').length ? tbl.getElementsByTagName('thead')[0].getElementsByTagName('tr') : tbl.getElementsByTagName('tr'); - rowArr = []; - sortableTable = false; - - for(var i = 0, tr; tr = allRowArr[i]; i++) { - if(tr.getElementsByTagName('td').length || !tr.getElementsByTagName('th').length) { continue; }; - rowArr[rowArr.length] = tr.getElementsByTagName('th'); - for(var j = 0, th; th = rowArr[rowArr.length - 1][j]; j++) { - if(th.className.search(/sortable/) != -1) { sortableTable = true; }; - }; - }; - - if(!sortableTable) continue; - - if(!tbl.id) { tbl.id = "fd-table-" + fdTableSort.uniqueHash++; }; - - showArrow = tbl.className.search("no-arrow") == -1; - showOnly = tbl.className.search("sortable-onload-show") != -1; - - columnNumSortObj = {}; - colMatch = fdTableSort.parseClassName(showOnly ? "sortable-onload-show" : "sortable-onload", tbl); - for(match = 1; match < colMatch.length; match++) { - columnNumSortObj[parseInt(colMatch[match], 10)] = { "reverse":colMatch[match].search("r") != -1 }; - }; - - rowLength = rowArr[0].length; - - for(c = 0;c < rowArr[0].length;c++){ - if(rowArr[0][c].getAttribute(fdTableSort.colspan) && rowArr[0][c].getAttribute(fdTableSort.colspan) > 1){ - rowLength = rowLength + (rowArr[0][c].getAttribute(fdTableSort.colspan) - 1); - }; - }; - - workArr = new Array(rowArr.length); - for(c = rowArr.length;c--;){ workArr[c]= new Array(rowLength); }; - - for(c = 0;c < workArr.length;c++){ - celCount = 0; - for(i = 0;i < rowLength;i++){ - if(!workArr[c][i]){ - cel = rowArr[c][celCount]; - colspan = (cel.getAttribute(fdTableSort.colspan) > 1) ? cel.getAttribute(fdTableSort.colspan):1; - rowspan = (cel.getAttribute(fdTableSort.rowspan) > 1) ? cel.getAttribute(fdTableSort.rowspan):1; - for(var t = 0;((t < colspan)&&((i+t) < rowLength));t++){ - for(var n = 0;((n < rowspan)&&((c+n) < workArr.length));n++) { - workArr[(c+n)][(i+t)] = cel; - }; - }; - if(++celCount == rowArr[c].length) break; - }; - }; - }; - - for(c = 0;c < workArr.length;c++) { - for(i = 0;i < workArr[c].length;i++){ - - 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; - - if(workArr[c][i].className.match('sortable')) { - workArr[c][i].className = workArr[c][i].className.replace(/forwardSort|reverseSort/, ""); - - if(i in columnNumSortObj) { - columnNumSortObj[i]["thNode"] = workArr[c][i]; - columnNumSortObj["active"] = true; - }; - - thtext = fdTableSort.getInnerText(workArr[c][i], true); - - for(var cn = workArr[c][i].childNodes.length; cn--;) { - // Skip image nodes and links created by the filter script. - if(workArr[c][i].childNodes[cn].nodeType == 1 && (workArr[c][i].childNodes[cn].className == "fdFilterTrigger" || /img/i.test(workArr[c][i].childNodes[cn].nodeName))) { - continue; - }; - if(workArr[c][i].childNodes[cn].nodeType == 1 && /^a$/i.test(workArr[c][i].childNodes[cn].nodeName)) { - workArr[c][i].childNodes[cn].onclick = workArr[c][i].childNodes[cn].onkeydown = null; - }; - workArr[c][i].removeChild(workArr[c][i].childNodes[cn]); - }; - - aclone = a.cloneNode(true); - //aclone.appendChild(document.createTextNode(thtext)); - aclone.innerHTML = thtext; - aclone.title = "Sort on \u201c" + thtext.replace('
', '') + "\u201d"; - aclone.onclick = aclone.onkeydown = workArr[c][i].onclick = fdTableSort.initWrapper; - workArr[c][i].appendChild(aclone); - if(showArrow) workArr[c][i].appendChild(span.cloneNode(false)); - workArr[c][i].className = workArr[c][i].className.replace(/fd-identical|fd-not-identical/, ""); - fdTableSort.disableSelection(workArr[c][i]); - aclone = null; - }; - }; - }; - - fdTableSort.tmpCache[tbl.id] = {cols:rowLength, headers:workArr}; - - workArr = null; - multi = 0; - - if("active" in columnNumSortObj) { - fdTableSort.tableId = tbl.id; - fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); - - delete columnNumSortObj["active"]; - - for(col in columnNumSortObj) { - obj = columnNumSortObj[col]; - if(!("thNode" in obj)) { continue; }; - fdTableSort.multi = true; - - len = obj.reverse ? 2 : 1; - - for(ii = 0; ii < len; ii++) { - fdTableSort.thNode = obj.thNode; - if(!showOnly) { - fdTableSort.initSort(false, true); - } else { - fdTableSort.addThNode(); - }; - }; - - if(showOnly) { - fdTableSort.removeClass(obj.thNode, "(forwardSort|reverseSort)"); - fdTableSort.addClass(obj.thNode, obj.reverse ? "reverseSort" : "forwardSort"); - if(showArrow) { - span = fdTableSort.thNode.getElementsByTagName('span')[0]; - if(span.firstChild) { span.removeChild(span.firstChild); }; - span.appendChild(document.createTextNode(len == 1 ? " \u2193" : " \u2191")); - }; - }; - }; - if(showOnly && (fdTableSort.tableCache[tbl.id].colStyle || fdTableSort.tableCache[tbl.id].rowStyle)) { - fdTableSort.redraw(tbl.id, false); - }; - } else if(tbl.className.search(/onload-zebra/) != -1) { - fdTableSort.tableId = tbl.id; - fdTableSort.prepareTableData(tbl); - if(fdTableSort.tableCache[tbl.id].rowStyle) { fdTableSort.redraw(tbl.id, false); }; - }; - }; - - fdTableSort.thNode = aclone = a = span = columnNumSortObj = thNode = tbl = allRowArr = rowArr = null; - }, - initWrapper: function(e) { - e = e || window.event; - var kc = e.type == "keydown" ? e.keyCode != null ? e.keyCode : e.charCode : -1; - if(fdTableSort.thNode == null && (e.type == "click" || kc == 13)) { - var targ = this; - while(targ.tagName.toLowerCase() != "th") { targ = targ.parentNode; }; - fdTableSort.thNode = targ; - while(targ.tagName.toLowerCase() != "table") { targ = targ.parentNode; }; - fdTableSort.tableId = targ.id; - fdTableSort.multi = e.shiftKey; - fdTableSort.addSortActiveClass(); - setTimeout(fdTableSort.initSort,5,false); - return fdTableSort.stopEvent(e); - }; - return kc != -1 ? true : fdTableSort.stopEvent(e); - }, - jsWrapper: function(tableid, colNums) { - if(!(tableid in fdTableSort.tmpCache)) { return false; }; - if(!(tableid in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(tableid)); }; - if(!(colNums instanceof Array)) { colNums = [colNums]; }; - - fdTableSort.tableId = tableid; - var len = colNums.length, colNum; - - if(fdTableSort.tableCache[tableid].thList.length == colNums.length) { - var identical = true; - var th; - for(var i = 0; i < len; i++) { - colNum = colNums[i]; - th = fdTableSort.tmpCache[tableid].headers[0][colNum]; - if(th != fdTableSort.tableCache[tableid].thList[i]) { - identical = false; - break; - }; - }; - if(identical) { - fdTableSort.thNode = th; - fdTableSort.initSort(true); - return; - }; - }; - - fdTableSort.addSortActiveClass(); - - for(var i = 0; i < len; i++) { - fdTableSort.multi = i; - colNum = colNums[i]; - fdTableSort.thNode = fdTableSort.tmpCache[tableid].headers[0][colNum]; - fdTableSort.initSort(true); - }; - }, - addSortActiveClass: function() { - if(fdTableSort.thNode == null) { return; }; - fdTableSort.addClass(fdTableSort.thNode, fdTableSort.sortActiveClass); - fdTableSort.addClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass); - }, - removeSortActiveClass: function() { - if(fdTableSort.thNode == null) return; - fdTableSort.removeClass(fdTableSort.thNode, fdTableSort.sortActiveClass); - fdTableSort.removeClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass); - }, - doCallback: function(init) { - if(!fdTableSort.tableId || !(fdTableSort.tableId in fdTableSort.tableCache)) { return; }; - fdTableSort.callback(fdTableSort.tableId, init ? fdTableSort.tableCache[fdTableSort.tableId].initiatedCallback : fdTableSort.tableCache[fdTableSort.tableId].completeCallback); - }, - addClass: function(e,c) { - if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) { return; }; - e.className += ( e.className ? " " : "" ) + c; - }, - /*@cc_on - /*@if (@_win32) - removeClass: function(e,c) { - e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1'); - }, - @else @*/ - removeClass: function(e,c) { - e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }, - /*@end - @*/ - callback: function(tblId, cb) { - var func, parts; - try { - if(cb.indexOf(".") != -1) { - parts = cb.split('.'); - obj = window; - for (var x = 0, part; part = obj[parts[x]]; x++) { - if(part instanceof Function) { - (function() { - var method = part; - func = function (data) { method.apply(obj, [data]) }; - })(); - } else { - obj = part; - }; - }; - } else if(cb + tblId in window) { - func = window[cb + tblId]; - } else if(cb in window) { - func = window[cb]; - } else { - func = null; - }; - } catch(err) {}; - - if(!(func instanceof Function)) return; - func(tblId, fdTableSort.tableCache[tblId].thList); - }, - prepareTableData: function(table) { - var data = []; - - var start = table.getElementsByTagName('tbody'); - start = start.length ? start[0] : table; - - var trs = start.rows; - var ths = table.getElementsByTagName('th'); - - var numberOfRows = trs.length; - var numberOfCols = fdTableSort.tmpCache[table.id].cols; - - var data = []; - var identical = new Array(numberOfCols); - var identVal = new Array(numberOfCols); - - for(var tmp = 0; tmp < numberOfCols; tmp++) identical[tmp] = true; - - var tr, td, th, txt, tds, col, row; - - var re = new RegExp(/fd-column-([0-9]+)/); - var rowCnt = 0; - - var sortableColumnNumbers = []; - - for(var tmp = 0, th; th = ths[tmp]; tmp++) { - if(th.className.search(re) == -1) continue; - sortableColumnNumbers[sortableColumnNumbers.length] = th; - }; - - for(row = 0; row < numberOfRows; row++) { - - tr = trs[row]; - if(tr.parentNode != start || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue; - data[rowCnt] = []; - tds = tr.cells; - - for(var tmp = 0, th; th = sortableColumnNumbers[tmp]; tmp++) { - col = th.className.match(re)[1]; - - td = tds[col]; - txt = fdTableSort.getInnerText(td) + " "; - txt = txt.replace(/^\s+/,'').replace(/\s+$/,''); - - if(th.className.search(/sortable-date/) != -1) { - txt = fdTableSort.dateFormat(txt, th.className.search(/sortable-date-dmy/) != -1); - } else if(th.className.search(/sortable-numeric|sortable-currency/) != -1) { - txt = parseFloat(txt.replace(/[^0-9\.\-]/g,'')); - if(isNaN(txt)) txt = ""; - } else if(th.className.search(/sortable-text/) != -1) { - txt = txt.toLowerCase(); - } else if (th.className.search(/sortable-keep/) != -1) { - txt = rowCnt; - } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1) { - if((th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData") in window) { - txt = window[th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData"](td, txt); - }; - } else if(txt != "") { - fdTableSort.removeClass(th, "sortable"); - if(fdTableSort.dateFormat(txt) != 0) { - fdTableSort.addClass(th, "sortable-date"); - txt = fdTableSort.dateFormat(txt); - } else if(txt.search(fdTableSort.regExp_Number) != -1 || txt.search(fdTableSort.regExp_Currency) != -1) { - fdTableSort.addClass(th, "sortable-numeric"); - txt = parseFloat(txt.replace(/[^0-9\.\-]/g,'')); - if(isNaN(txt)) txt = ""; - } else { - fdTableSort.addClass(th, "sortable-text"); - txt = txt.toLowerCase(); - }; - }; - - if(rowCnt > 0 && identical[col] && identVal[col] != txt) { identical[col] = false; }; - - identVal[col] = txt; - data[rowCnt][col] = txt; - }; - data[rowCnt][numberOfCols] = tr; - rowCnt++; - }; - - var colStyle = table.className.search(/colstyle-([\S]+)/) != -1 ? table.className.match(/colstyle-([\S]+)/)[1] : false; - var rowStyle = table.className.search(/rowstyle-([\S]+)/) != -1 ? table.className.match(/rowstyle-([\S]+)/)[1] : false; - var iCBack = table.className.search(/sortinitiatedcallback-([\S-]+)/) == -1 ? "sortInitiatedCallback" : table.className.match(/sortinitiatedcallback-([\S]+)/)[1]; - var cCBack = table.className.search(/sortcompletecallback-([\S-]+)/) == -1 ? "sortCompleteCallback" : table.className.match(/sortcompletecallback-([\S]+)/)[1]; - iCBack = iCBack.replace("-", "."); - cCBack = cCBack.replace("-", "."); - 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 }; - sortableColumnNumbers = data = tr = td = th = trs = identical = identVal = null; - }, - onUnload: function() { - for(tbl in fdTableSort.tableCache) { fdTableSort.removeTableCache(tbl); }; - for(tbl in fdTableSort.tmpCache) { fdTableSort.removeTmpCache(tbl); }; - fdTableSort.removeEvent(window, "load", fdTableSort.initEvt); - fdTableSort.removeEvent(window, "unload", fdTableSort.onUnload); - fdTableSort.tmpCache = fdTableSort.tableCache = null; - }, - addThNode: function() { - var dataObj = fdTableSort.tableCache[fdTableSort.tableId]; - var pos = fdTableSort.thNode.className.match(/fd-column-([0-9]+)/)[1]; - var alt = false; - - if(!fdTableSort.multi) { - if(dataObj.colStyle) { - var len = dataObj.thList.length; - for(var i = 0; i < len; i++) { - dataObj.colOrder[dataObj.thList[i].className.match(/fd-column-([0-9]+)/)[1]] = false; - }; - }; - if(dataObj.thList.length && dataObj.thList[0] == fdTableSort.thNode) alt = true; - dataObj.thList = []; - }; - - var found = false; - var l = dataObj.thList.length; - - for(var i = 0, n; n = dataObj.thList[i]; i++) { - if(n == fdTableSort.thNode) { - found = true; - break; - }; - }; - - if(!found) { - dataObj.thList.push(fdTableSort.thNode); - if(dataObj.colStyle) { dataObj.colOrder[pos] = true; }; - }; - - var ths = document.getElementById(fdTableSort.tableId).getElementsByTagName("th"); - for(var i = 0, th; th = ths[i]; i++) { - found = false; - for(var z = 0, n; n = dataObj.thList[z]; z++) { - if(n == th) { - found = true; - break; - }; - }; - if(!found) { - fdTableSort.removeClass(th, "(forwardSort|reverseSort)"); - if(!dataObj.noArrow) { - span = th.getElementsByTagName('span'); - if(span.length) { - span = span[0]; - while(span.firstChild) span.removeChild(span.firstChild); - }; - }; - }; - }; - - if(dataObj.thList.length > 1) { - classToAdd = fdTableSort.thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort"; - fdTableSort.removeClass(fdTableSort.thNode, "(forwardSort|reverseSort)"); - fdTableSort.addClass(fdTableSort.thNode, classToAdd); - dataObj.pos = -1 - } else if(alt) { dataObj.pos = fdTableSort.thNode }; - }, - initSort: function(noCallback, ident) { - var thNode = fdTableSort.thNode; - var tableElem = document.getElementById(fdTableSort.tableId); - - if(!(fdTableSort.tableId in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); }; - - fdTableSort.addThNode(); - - if(!noCallback) { fdTableSort.doCallback(true); }; - - fdTableSort.pos = thNode.className.match(/fd-column-([0-9]+)/)[1]; - var dataObj = fdTableSort.tableCache[tableElem.id]; - var lastPos = dataObj.pos && dataObj.pos.className ? dataObj.pos.className.match(/fd-column-([0-9]+)/)[1] : -1; - var len1 = dataObj.data.length; - var len2 = dataObj.data.length > 0 ? dataObj.data[0].length - 1 : 0; - var identical = dataObj.identical[fdTableSort.pos]; - var classToAdd = "forwardSort"; - - if(dataObj.thList.length > 1) { - var js = "var sortWrapper = function(a,b) {\n"; - var l = dataObj.thList.length; - var cnt = 0; - var e,d,th,p,f; - - for(var i=0; i < l; i++) { - th = dataObj.thList[i]; - p = th.className.match(/fd-column-([0-9]+)/)[1]; - if(dataObj.identical[p]) { continue; }; - cnt++; - - if(th.className.match(/sortable-(numeric|currency|date|keep)/)) { - f = "fdTableSort.sortNumeric"; - } else if(th.className.match('sortable-text')) { - f = "fdTableSort.sortText"; - } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && th.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) { - f = "window['" + th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "']"; - } else f = "fdTableSort.sortText"; - - e = "e" + i; - d = th.className.search('forwardSort') != -1 ? "a,b" : "b,a"; - js += "fdTableSort.pos = " + p + ";\n"; - js += "var " + e + " = "+f+"(" + d +");\n"; - js += "if(" + e + ") return " + e + ";\n"; - js += "else { \n"; - }; - - js += "return 0;\n"; - - for(var i=0; i < cnt; i++) { - js += "};\n"; - }; - - if(cnt) js += "return 0;\n"; - js += "};\n"; - - eval(js); - dataObj.data.sort(sortWrapper); - identical = false; - } else if((lastPos == fdTableSort.pos && !identical) || (thNode.className.search(/sortable-keep/) != -1 && lastPos == -1)) { - dataObj.data.reverse(); - classToAdd = thNode.className.search(/reverseSort/) != -1 ? "forwardSort" : "reverseSort"; - if(thNode.className.search(/sortable-keep/) != -1 && lastPos == -1) fdTableSort.tableCache[tableElem.id].pos = thNode; - } else { - fdTableSort.tableCache[tableElem.id].pos = thNode; - classToAdd = thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort"; - if(!identical) { - if(thNode.className.match(/sortable-(numeric|currency|date|keep)/)) { - dataObj.data.sort(fdTableSort.sortNumeric); - } else if(thNode.className.match('sortable-text')) { - dataObj.data.sort(fdTableSort.sortText); - } else if(thNode.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) { - dataObj.data.sort(window[thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1]]); - }; - - if(thNode.className.search(/(^|\s)favour-reverse($|\s)/) != -1) { - classToAdd = classToAdd == "forwardSort" ? "reverseSort" : "forwardSort"; - dataObj.data.reverse(); - }; - }; - }; - if(ident) { identical = false; }; - if(dataObj.thList.length == 1) { - fdTableSort.removeClass(thNode, "(forwardSort|reverseSort)"); - fdTableSort.addClass(thNode, classToAdd); - }; - if(!dataObj.noArrow) { - var span = fdTableSort.thNode.getElementsByTagName('span')[0]; - if(span.firstChild) span.removeChild(span.firstChild); - span.appendChild(document.createTextNode(fdTableSort.thNode.className.search(/forwardSort/) != -1 ? " \u2193" : " \u2191")); - }; - if(!dataObj.rowStyle && !dataObj.colStyle && identical) { - fdTableSort.removeSortActiveClass(); - if(!noCallback) { fdTableSort.doCallback(false); }; - fdTableSort.thNode = null; - return; - }; - if("tablePaginater" in window && tablePaginater.tableIsPaginated(fdTableSort.tableId)) { - tablePaginater.redraw(fdTableSort.tableId, identical); - } else { - fdTableSort.redraw(fdTableSort.tableId, identical); - }; - fdTableSort.removeSortActiveClass(); - if(!noCallback) { fdTableSort.doCallback(false); }; - fdTableSort.thNode = null; - }, - redraw: function(tableid, identical) { - if(!tableid || !(tableid in fdTableSort.tableCache)) { return; }; - var dataObj = fdTableSort.tableCache[tableid]; - var data = dataObj.data; - var len1 = data.length; - var len2 = len1 ? data[0].length - 1 : 0; - var hook = dataObj.hook; - var colStyle = dataObj.colStyle; - var rowStyle = dataObj.rowStyle; - var colOrder = dataObj.colOrder; - var highLight = 0; - var reg = /(^|\s)invisibleRow(\s|$)/; - var tr, tds; - - for(var i = 0; i < len1; i++) { - tr = data[i][len2]; - if(colStyle) { - tds = tr.cells; - for(thPos in colOrder) { - if(!colOrder[thPos]) fdTableSort.removeClass(tds[thPos], colStyle); - else fdTableSort.addClass(tds[thPos], colStyle); - }; - }; - if(!identical) { - if(rowStyle && tr.className.search(reg) == -1) { - if(highLight++ & 1) fdTableSort.addClass(tr, rowStyle); - else fdTableSort.removeClass(tr, rowStyle); - }; - - // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser - // hook.removeChild(tr); - hook.appendChild(tr); - }; - }; - tr = tds = hook = null; - }, - getInnerText: function(el, allowBrTags) { - if (typeof el == "string" || typeof el == "undefined") return el; - if(el.innerText) return el.innerText; - var txt = '', i; - for(i = el.firstChild; i; i = i.nextSibling) { - if(allowBrTags && i.nodeName && i.nodeName == "BR") txt += "
"; - else if(i.nodeType == 3) txt += i.nodeValue; - else if(i.nodeType == 1) txt += fdTableSort.getInnerText(i); - }; - return txt; - }, - dateFormat: function(dateIn, favourDMY) { - var dateTest = [ - { 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 - { 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 - { 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 - ]; - var start, cnt = 0, numFormats = dateTest.length; - while(cnt < numFormats) { - start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats; - if(dateIn.match(dateTest[start].regExp)) { - res = dateIn.match(dateTest[start].regExp); - y = res[dateTest[start].y]; - m = res[dateTest[start].m]; - d = res[dateTest[start].d]; - if(m.length == 1) m = "0" + String(m); - if(d.length == 1) d = "0" + String(d); - if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y); - - return y+String(m)+d; - }; - cnt++; - }; - return 0; - }, - sortNumeric:function(a,b) { - var aa = a[fdTableSort.pos]; - var bb = b[fdTableSort.pos]; - if(aa == bb) return 0; - if(aa === "" && !isNaN(bb)) return -1; - if(bb === "" && !isNaN(aa)) return 1; - return aa - bb; - }, - sortText:function(a,b) { - var aa = a[fdTableSort.pos]; - var bb = b[fdTableSort.pos]; - if(aa == bb) return 0; - if(aa < bb) return -1; - return 1; - } -}; -})(); -fdTableSort.addEvent(window, "load", fdTableSort.initEvt); -fdTableSort.addEvent(window, "unload", fdTableSort.onUnload); +/* + TableSort revisited v5.0 by frequency-decoder.com + + Released under a creative commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/) + + Please credit frequency decoder in any derivative work - thanks + + You are free: + + * to copy, distribute, display, and perform the work + * to make derivative works + * to make commercial use of the work + + Under the following conditions: + + by Attribution. + -------------- + You must attribute the work in the manner specified by the author or licensor. + + sa + -- + 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. + + * For any reuse or distribution, you must make clear to others the license terms of this work. + * Any of these conditions can be waived if you get permission from the copyright holder. +*/ + +(function() { +fdTableSort = { + regExp_Currency: /^[£$€¥¤]/, + regExp_Number: /^(\-)?[0-9]+(\.[0-9]*)?$/, + pos: -1, + uniqueHash: 1, + thNode: null, + tableId: null, + tableCache: {}, + tmpCache: {}, + sortActiveClass: "sort-active", + /*@cc_on + /*@if (@_win32) + colspan: "colSpan", + rowspan: "rowSpan", + @else @*/ + colspan: "colspan", + rowspan: "rowspan", + /*@end + @*/ + + addEvent: function(obj, type, fn, tmp) { + tmp || (tmp = true); + if( obj.attachEvent ) { + obj["e"+type+fn] = fn; + obj[type+fn] = function(){obj["e"+type+fn]( window.event );}; + obj.attachEvent( "on"+type, obj[type+fn] ); + } else { + obj.addEventListener( type, fn, true ); + }; + }, + removeEvent: function(obj, type, fn, tmp) { + tmp || (tmp = true); + try { + if( obj.detachEvent ) { + obj.detachEvent( "on"+type, obj[type+fn] ); + obj[type+fn] = null; + } else { + obj.removeEventListener( type, fn, true ); + }; + } catch(err) {}; + }, + stopEvent: function(e) { + e = e || window.event; + + if(e.stopPropagation) { + e.stopPropagation(); + e.preventDefault(); + }; + + /*@cc_on@*/ + /*@if(@_win32) + e.cancelBubble = true; + e.returnValue = false; + /*@end@*/ + return false; + }, + parseClassName: function(head, tbl) { + var colMatch = tbl.className.match(new RegExp(head + "((-[\\d]+([r]){0,1})+)")); + return colMatch && colMatch.length ? colMatch[0].replace(head, "").split("-") : []; + }, + disableSelection: function(element) { + element.onselectstart = function() { + return false; + }; + element.unselectable = "on"; + element.style.MozUserSelect = "none"; + }, + removeTableCache: function(tableId) { + if(!(tableId in fdTableSort.tableCache)) return; + + fdTableSort.tableCache[tableId] = null; + delete fdTableSort.tableCache[tableId]; + + var tbl = document.getElementById(tableId); + if(!tbl) return; + var ths = tbl.getElementsByTagName("th"); + var a; + for(var i = 0, th; th = ths[i]; i++) { + a = th.getElementsByTagName("a"); + if(a.length) a[0].onkeydown = a[0].onclick = null; + th.onclick = th.onselectstart = th = a = null; + }; + }, + removeTmpCache: function(tableId) { + if(!(tableId in fdTableSort.tmpCache)) return; + var headers = fdTableSort.tmpCache[tableId].headers; + var a; + for(var i = 0, row; row = headers[i]; i++) { + for(var j = 0, th; th = row[j]; j++) { + a = th.getElementsByTagName("a"); + if(a.length) a[0].onkeydown = a[0].onclick = null; + th.onclick = th.onselectstart = th = a = null; + }; + }; + fdTableSort.tmpCache[tableId] = null; + delete fdTableSort.tmpCache[tableId]; + }, + initEvt: function(e) { + fdTableSort.init(false); + }, + init: function(tableId) { + if (!document.getElementsByTagName || !document.createElement || !document.getElementById) return; + + var tables = tableId && document.getElementById(tableId) ? [document.getElementById(tableId)] : document.getElementsByTagName("table"); + var c, ii, len, colMatch, showOnly, match, showArrow, columnNumSortObj, obj, workArr, headers, thtext, aclone, multi, colCnt, cel, allRowArr, rowArr, sortableTable, celCount, colspan, rowspan, rowLength; + + var a = document.createElement("a"); + a.href = "#"; + a.className = "fdTableSortTrigger"; + + var span = document.createElement("span"); + + for(var k = 0, tbl; tbl = tables[k]; k++) { + + if(tbl.id) { + fdTableSort.removeTableCache(tbl.id); + fdTableSort.removeTmpCache(tbl.id); + }; + + allRowArr = tbl.getElementsByTagName('thead').length ? tbl.getElementsByTagName('thead')[0].getElementsByTagName('tr') : tbl.getElementsByTagName('tr'); + rowArr = []; + sortableTable = false; + + for(var i = 0, tr; tr = allRowArr[i]; i++) { + if(tr.getElementsByTagName('td').length || !tr.getElementsByTagName('th').length) { continue; }; + rowArr[rowArr.length] = tr.getElementsByTagName('th'); + for(var j = 0, th; th = rowArr[rowArr.length - 1][j]; j++) { + if(th.className.search(/sortable/) != -1) { sortableTable = true; }; + }; + }; + + if(!sortableTable) continue; + + if(!tbl.id) { tbl.id = "fd-table-" + fdTableSort.uniqueHash++; }; + + showArrow = tbl.className.search("no-arrow") == -1; + showOnly = tbl.className.search("sortable-onload-show") != -1; + + columnNumSortObj = {}; + colMatch = fdTableSort.parseClassName(showOnly ? "sortable-onload-show" : "sortable-onload", tbl); + for(match = 1; match < colMatch.length; match++) { + columnNumSortObj[parseInt(colMatch[match], 10)] = { "reverse":colMatch[match].search("r") != -1 }; + }; + + rowLength = rowArr[0].length; + + for(c = 0;c < rowArr[0].length;c++){ + if(rowArr[0][c].getAttribute(fdTableSort.colspan) && rowArr[0][c].getAttribute(fdTableSort.colspan) > 1){ + rowLength = rowLength + (rowArr[0][c].getAttribute(fdTableSort.colspan) - 1); + }; + }; + + workArr = new Array(rowArr.length); + for(c = rowArr.length;c--;){ workArr[c]= new Array(rowLength); }; + + for(c = 0;c < workArr.length;c++){ + celCount = 0; + for(i = 0;i < rowLength;i++){ + if(!workArr[c][i]){ + cel = rowArr[c][celCount]; + colspan = (cel.getAttribute(fdTableSort.colspan) > 1) ? cel.getAttribute(fdTableSort.colspan):1; + rowspan = (cel.getAttribute(fdTableSort.rowspan) > 1) ? cel.getAttribute(fdTableSort.rowspan):1; + for(var t = 0;((t < colspan)&&((i+t) < rowLength));t++){ + for(var n = 0;((n < rowspan)&&((c+n) < workArr.length));n++) { + workArr[(c+n)][(i+t)] = cel; + }; + }; + if(++celCount == rowArr[c].length) break; + }; + }; + }; + + for(c = 0;c < workArr.length;c++) { + for(i = 0;i < workArr[c].length;i++){ + + 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; + + if(workArr[c][i].className.match('sortable')) { + workArr[c][i].className = workArr[c][i].className.replace(/forwardSort|reverseSort/, ""); + + if(i in columnNumSortObj) { + columnNumSortObj[i]["thNode"] = workArr[c][i]; + columnNumSortObj["active"] = true; + }; + + thtext = fdTableSort.getInnerText(workArr[c][i], true); + + for(var cn = workArr[c][i].childNodes.length; cn--;) { + // Skip image nodes and links created by the filter script. + if(workArr[c][i].childNodes[cn].nodeType == 1 && (workArr[c][i].childNodes[cn].className == "fdFilterTrigger" || /img/i.test(workArr[c][i].childNodes[cn].nodeName))) { + continue; + }; + if(workArr[c][i].childNodes[cn].nodeType == 1 && /^a$/i.test(workArr[c][i].childNodes[cn].nodeName)) { + workArr[c][i].childNodes[cn].onclick = workArr[c][i].childNodes[cn].onkeydown = null; + }; + workArr[c][i].removeChild(workArr[c][i].childNodes[cn]); + }; + + aclone = a.cloneNode(true); + //aclone.appendChild(document.createTextNode(thtext)); + aclone.innerHTML = thtext; + aclone.title = "Sort on \u201c" + thtext.replace('
', '') + "\u201d"; + aclone.onclick = aclone.onkeydown = workArr[c][i].onclick = fdTableSort.initWrapper; + workArr[c][i].appendChild(aclone); + if(showArrow) workArr[c][i].appendChild(span.cloneNode(false)); + workArr[c][i].className = workArr[c][i].className.replace(/fd-identical|fd-not-identical/, ""); + fdTableSort.disableSelection(workArr[c][i]); + aclone = null; + }; + }; + }; + + fdTableSort.tmpCache[tbl.id] = {cols:rowLength, headers:workArr}; + + workArr = null; + multi = 0; + + if("active" in columnNumSortObj) { + fdTableSort.tableId = tbl.id; + fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); + + delete columnNumSortObj["active"]; + + for(col in columnNumSortObj) { + obj = columnNumSortObj[col]; + if(!("thNode" in obj)) { continue; }; + fdTableSort.multi = true; + + len = obj.reverse ? 2 : 1; + + for(ii = 0; ii < len; ii++) { + fdTableSort.thNode = obj.thNode; + if(!showOnly) { + fdTableSort.initSort(false, true); + } else { + fdTableSort.addThNode(); + }; + }; + + if(showOnly) { + fdTableSort.removeClass(obj.thNode, "(forwardSort|reverseSort)"); + fdTableSort.addClass(obj.thNode, obj.reverse ? "reverseSort" : "forwardSort"); + if(showArrow) { + span = fdTableSort.thNode.getElementsByTagName('span')[0]; + if(span.firstChild) { span.removeChild(span.firstChild); }; + span.appendChild(document.createTextNode(len == 1 ? " \u2193" : " \u2191")); + }; + }; + }; + if(showOnly && (fdTableSort.tableCache[tbl.id].colStyle || fdTableSort.tableCache[tbl.id].rowStyle)) { + fdTableSort.redraw(tbl.id, false); + }; + } else if(tbl.className.search(/onload-zebra/) != -1) { + fdTableSort.tableId = tbl.id; + fdTableSort.prepareTableData(tbl); + if(fdTableSort.tableCache[tbl.id].rowStyle) { fdTableSort.redraw(tbl.id, false); }; + }; + }; + + fdTableSort.thNode = aclone = a = span = columnNumSortObj = thNode = tbl = allRowArr = rowArr = null; + }, + initWrapper: function(e) { + e = e || window.event; + var kc = e.type == "keydown" ? e.keyCode != null ? e.keyCode : e.charCode : -1; + if(fdTableSort.thNode == null && (e.type == "click" || kc == 13)) { + var targ = this; + while(targ.tagName.toLowerCase() != "th") { targ = targ.parentNode; }; + fdTableSort.thNode = targ; + while(targ.tagName.toLowerCase() != "table") { targ = targ.parentNode; }; + fdTableSort.tableId = targ.id; + fdTableSort.multi = e.shiftKey; + fdTableSort.addSortActiveClass(); + setTimeout(fdTableSort.initSort,5,false); + return fdTableSort.stopEvent(e); + }; + return kc != -1 ? true : fdTableSort.stopEvent(e); + }, + jsWrapper: function(tableid, colNums) { + if(!(tableid in fdTableSort.tmpCache)) { return false; }; + if(!(tableid in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(tableid)); }; + if(!(colNums instanceof Array)) { colNums = [colNums]; }; + + fdTableSort.tableId = tableid; + var len = colNums.length, colNum; + + if(fdTableSort.tableCache[tableid].thList.length == colNums.length) { + var identical = true; + var th; + for(var i = 0; i < len; i++) { + colNum = colNums[i]; + th = fdTableSort.tmpCache[tableid].headers[0][colNum]; + if(th != fdTableSort.tableCache[tableid].thList[i]) { + identical = false; + break; + }; + }; + if(identical) { + fdTableSort.thNode = th; + fdTableSort.initSort(true); + return; + }; + }; + + fdTableSort.addSortActiveClass(); + + for(var i = 0; i < len; i++) { + fdTableSort.multi = i; + colNum = colNums[i]; + fdTableSort.thNode = fdTableSort.tmpCache[tableid].headers[0][colNum]; + fdTableSort.initSort(true); + }; + }, + addSortActiveClass: function() { + if(fdTableSort.thNode == null) { return; }; + fdTableSort.addClass(fdTableSort.thNode, fdTableSort.sortActiveClass); + fdTableSort.addClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass); + }, + removeSortActiveClass: function() { + if(fdTableSort.thNode == null) return; + fdTableSort.removeClass(fdTableSort.thNode, fdTableSort.sortActiveClass); + fdTableSort.removeClass(document.getElementsByTagName('body')[0], fdTableSort.sortActiveClass); + }, + doCallback: function(init) { + if(!fdTableSort.tableId || !(fdTableSort.tableId in fdTableSort.tableCache)) { return; }; + fdTableSort.callback(fdTableSort.tableId, init ? fdTableSort.tableCache[fdTableSort.tableId].initiatedCallback : fdTableSort.tableCache[fdTableSort.tableId].completeCallback); + }, + addClass: function(e,c) { + if(new RegExp("(^|\\s)" + c + "(\\s|$)").test(e.className)) { return; }; + e.className += ( e.className ? " " : "" ) + c; + }, + /*@cc_on + /*@if (@_win32) + removeClass: function(e,c) { + e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s*((?:[\S\s]*\S)?)\s*$/, '$1'); + }, + @else @*/ + removeClass: function(e,c) { + e.className = !c ? "" : e.className.replace(new RegExp("(^|\\s)" + c + "(\\s|$)"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }, + /*@end + @*/ + callback: function(tblId, cb) { + var func, parts; + try { + if(cb.indexOf(".") != -1) { + parts = cb.split('.'); + obj = window; + for (var x = 0, part; part = obj[parts[x]]; x++) { + if(part instanceof Function) { + (function() { + var method = part; + func = function (data) { method.apply(obj, [data]) }; + })(); + } else { + obj = part; + }; + }; + } else if(cb + tblId in window) { + func = window[cb + tblId]; + } else if(cb in window) { + func = window[cb]; + } else { + func = null; + }; + } catch(err) {}; + + if(!(func instanceof Function)) return; + func(tblId, fdTableSort.tableCache[tblId].thList); + }, + prepareTableData: function(table) { + var data = []; + + var start = table.getElementsByTagName('tbody'); + start = start.length ? start[0] : table; + + var trs = start.rows; + var ths = table.getElementsByTagName('th'); + + var numberOfRows = trs.length; + var numberOfCols = fdTableSort.tmpCache[table.id].cols; + + var data = []; + var identical = new Array(numberOfCols); + var identVal = new Array(numberOfCols); + + for(var tmp = 0; tmp < numberOfCols; tmp++) identical[tmp] = true; + + var tr, td, th, txt, tds, col, row; + + var re = new RegExp(/fd-column-([0-9]+)/); + var rowCnt = 0; + + var sortableColumnNumbers = []; + + for(var tmp = 0, th; th = ths[tmp]; tmp++) { + if(th.className.search(re) == -1) continue; + sortableColumnNumbers[sortableColumnNumbers.length] = th; + }; + + for(row = 0; row < numberOfRows; row++) { + + tr = trs[row]; + if(tr.parentNode != start || tr.getElementsByTagName("th").length || (tr.parentNode && tr.parentNode.tagName.toLowerCase().search(/thead|tfoot/) != -1)) continue; + data[rowCnt] = []; + tds = tr.cells; + + for(var tmp = 0, th; th = sortableColumnNumbers[tmp]; tmp++) { + col = th.className.match(re)[1]; + + td = tds[col]; + txt = fdTableSort.getInnerText(td) + " "; + txt = txt.replace(/^\s+/,'').replace(/\s+$/,''); + + if(th.className.search(/sortable-date/) != -1) { + txt = fdTableSort.dateFormat(txt, th.className.search(/sortable-date-dmy/) != -1); + } else if(th.className.search(/sortable-numeric|sortable-currency/) != -1) { + txt = parseFloat(txt.replace(/[^0-9\.\-]/g,'')); + if(isNaN(txt)) txt = ""; + } else if(th.className.search(/sortable-text/) != -1) { + txt = txt.toLowerCase(); + } else if (th.className.search(/sortable-keep/) != -1) { + txt = rowCnt; + } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1) { + if((th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData") in window) { + txt = window[th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "PrepareData"](td, txt); + }; + } else if(txt != "") { + fdTableSort.removeClass(th, "sortable"); + if(fdTableSort.dateFormat(txt) != 0) { + fdTableSort.addClass(th, "sortable-date"); + txt = fdTableSort.dateFormat(txt); + } else if(txt.search(fdTableSort.regExp_Number) != -1 || txt.search(fdTableSort.regExp_Currency) != -1) { + fdTableSort.addClass(th, "sortable-numeric"); + txt = parseFloat(txt.replace(/[^0-9\.\-]/g,'')); + if(isNaN(txt)) txt = ""; + } else { + fdTableSort.addClass(th, "sortable-text"); + txt = txt.toLowerCase(); + }; + }; + + if(rowCnt > 0 && identical[col] && identVal[col] != txt) { identical[col] = false; }; + + identVal[col] = txt; + data[rowCnt][col] = txt; + }; + data[rowCnt][numberOfCols] = tr; + rowCnt++; + }; + + var colStyle = table.className.search(/colstyle-([\S]+)/) != -1 ? table.className.match(/colstyle-([\S]+)/)[1] : false; + var rowStyle = table.className.search(/rowstyle-([\S]+)/) != -1 ? table.className.match(/rowstyle-([\S]+)/)[1] : false; + var iCBack = table.className.search(/sortinitiatedcallback-([\S-]+)/) == -1 ? "sortInitiatedCallback" : table.className.match(/sortinitiatedcallback-([\S]+)/)[1]; + var cCBack = table.className.search(/sortcompletecallback-([\S-]+)/) == -1 ? "sortCompleteCallback" : table.className.match(/sortcompletecallback-([\S]+)/)[1]; + iCBack = iCBack.replace("-", "."); + cCBack = cCBack.replace("-", "."); + 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 }; + sortableColumnNumbers = data = tr = td = th = trs = identical = identVal = null; + }, + onUnload: function() { + for(tbl in fdTableSort.tableCache) { fdTableSort.removeTableCache(tbl); }; + for(tbl in fdTableSort.tmpCache) { fdTableSort.removeTmpCache(tbl); }; + fdTableSort.removeEvent(window, "load", fdTableSort.initEvt); + fdTableSort.removeEvent(window, "unload", fdTableSort.onUnload); + fdTableSort.tmpCache = fdTableSort.tableCache = null; + }, + addThNode: function() { + var dataObj = fdTableSort.tableCache[fdTableSort.tableId]; + var pos = fdTableSort.thNode.className.match(/fd-column-([0-9]+)/)[1]; + var alt = false; + + if(!fdTableSort.multi) { + if(dataObj.colStyle) { + var len = dataObj.thList.length; + for(var i = 0; i < len; i++) { + dataObj.colOrder[dataObj.thList[i].className.match(/fd-column-([0-9]+)/)[1]] = false; + }; + }; + if(dataObj.thList.length && dataObj.thList[0] == fdTableSort.thNode) alt = true; + dataObj.thList = []; + }; + + var found = false; + var l = dataObj.thList.length; + + for(var i = 0, n; n = dataObj.thList[i]; i++) { + if(n == fdTableSort.thNode) { + found = true; + break; + }; + }; + + if(!found) { + dataObj.thList.push(fdTableSort.thNode); + if(dataObj.colStyle) { dataObj.colOrder[pos] = true; }; + }; + + var ths = document.getElementById(fdTableSort.tableId).getElementsByTagName("th"); + for(var i = 0, th; th = ths[i]; i++) { + found = false; + for(var z = 0, n; n = dataObj.thList[z]; z++) { + if(n == th) { + found = true; + break; + }; + }; + if(!found) { + fdTableSort.removeClass(th, "(forwardSort|reverseSort)"); + if(!dataObj.noArrow) { + span = th.getElementsByTagName('span'); + if(span.length) { + span = span[0]; + while(span.firstChild) span.removeChild(span.firstChild); + }; + }; + }; + }; + + if(dataObj.thList.length > 1) { + classToAdd = fdTableSort.thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort"; + fdTableSort.removeClass(fdTableSort.thNode, "(forwardSort|reverseSort)"); + fdTableSort.addClass(fdTableSort.thNode, classToAdd); + dataObj.pos = -1 + } else if(alt) { dataObj.pos = fdTableSort.thNode }; + }, + initSort: function(noCallback, ident) { + var thNode = fdTableSort.thNode; + var tableElem = document.getElementById(fdTableSort.tableId); + + if(!(fdTableSort.tableId in fdTableSort.tableCache)) { fdTableSort.prepareTableData(document.getElementById(fdTableSort.tableId)); }; + + fdTableSort.addThNode(); + + if(!noCallback) { fdTableSort.doCallback(true); }; + + fdTableSort.pos = thNode.className.match(/fd-column-([0-9]+)/)[1]; + var dataObj = fdTableSort.tableCache[tableElem.id]; + var lastPos = dataObj.pos && dataObj.pos.className ? dataObj.pos.className.match(/fd-column-([0-9]+)/)[1] : -1; + var len1 = dataObj.data.length; + var len2 = dataObj.data.length > 0 ? dataObj.data[0].length - 1 : 0; + var identical = dataObj.identical[fdTableSort.pos]; + var classToAdd = "forwardSort"; + + if(dataObj.thList.length > 1) { + var js = "var sortWrapper = function(a,b) {\n"; + var l = dataObj.thList.length; + var cnt = 0; + var e,d,th,p,f; + + for(var i=0; i < l; i++) { + th = dataObj.thList[i]; + p = th.className.match(/fd-column-([0-9]+)/)[1]; + if(dataObj.identical[p]) { continue; }; + cnt++; + + if(th.className.match(/sortable-(numeric|currency|date|keep)/)) { + f = "fdTableSort.sortNumeric"; + } else if(th.className.match('sortable-text')) { + f = "fdTableSort.sortText"; + } else if(th.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && th.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) { + f = "window['" + th.className.match(/sortable-([a-zA-Z\_]+)/)[1] + "']"; + } else f = "fdTableSort.sortText"; + + e = "e" + i; + d = th.className.search('forwardSort') != -1 ? "a,b" : "b,a"; + js += "fdTableSort.pos = " + p + ";\n"; + js += "var " + e + " = "+f+"(" + d +");\n"; + js += "if(" + e + ") return " + e + ";\n"; + js += "else { \n"; + }; + + js += "return 0;\n"; + + for(var i=0; i < cnt; i++) { + js += "};\n"; + }; + + if(cnt) js += "return 0;\n"; + js += "};\n"; + + eval(js); + dataObj.data.sort(sortWrapper); + identical = false; + } else if((lastPos == fdTableSort.pos && !identical) || (thNode.className.search(/sortable-keep/) != -1 && lastPos == -1)) { + dataObj.data.reverse(); + classToAdd = thNode.className.search(/reverseSort/) != -1 ? "forwardSort" : "reverseSort"; + if(thNode.className.search(/sortable-keep/) != -1 && lastPos == -1) fdTableSort.tableCache[tableElem.id].pos = thNode; + } else { + fdTableSort.tableCache[tableElem.id].pos = thNode; + classToAdd = thNode.className.search(/forwardSort/) != -1 ? "reverseSort" : "forwardSort"; + if(!identical) { + if(thNode.className.match(/sortable-(numeric|currency|date|keep)/)) { + dataObj.data.sort(fdTableSort.sortNumeric); + } else if(thNode.className.match('sortable-text')) { + dataObj.data.sort(fdTableSort.sortText); + } else if(thNode.className.search(/sortable-([a-zA-Z\_]+)/) != -1 && thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1] in window) { + dataObj.data.sort(window[thNode.className.match(/sortable-([a-zA-Z\_]+)/)[1]]); + }; + + if(thNode.className.search(/(^|\s)favour-reverse($|\s)/) != -1) { + classToAdd = classToAdd == "forwardSort" ? "reverseSort" : "forwardSort"; + dataObj.data.reverse(); + }; + }; + }; + if(ident) { identical = false; }; + if(dataObj.thList.length == 1) { + fdTableSort.removeClass(thNode, "(forwardSort|reverseSort)"); + fdTableSort.addClass(thNode, classToAdd); + }; + if(!dataObj.noArrow) { + var span = fdTableSort.thNode.getElementsByTagName('span')[0]; + if(span.firstChild) span.removeChild(span.firstChild); + span.appendChild(document.createTextNode(fdTableSort.thNode.className.search(/forwardSort/) != -1 ? " \u2193" : " \u2191")); + }; + if(!dataObj.rowStyle && !dataObj.colStyle && identical) { + fdTableSort.removeSortActiveClass(); + if(!noCallback) { fdTableSort.doCallback(false); }; + fdTableSort.thNode = null; + return; + }; + if("tablePaginater" in window && tablePaginater.tableIsPaginated(fdTableSort.tableId)) { + tablePaginater.redraw(fdTableSort.tableId, identical); + } else { + fdTableSort.redraw(fdTableSort.tableId, identical); + }; + fdTableSort.removeSortActiveClass(); + if(!noCallback) { fdTableSort.doCallback(false); }; + fdTableSort.thNode = null; + }, + redraw: function(tableid, identical) { + if(!tableid || !(tableid in fdTableSort.tableCache)) { return; }; + var dataObj = fdTableSort.tableCache[tableid]; + var data = dataObj.data; + var len1 = data.length; + var len2 = len1 ? data[0].length - 1 : 0; + var hook = dataObj.hook; + var colStyle = dataObj.colStyle; + var rowStyle = dataObj.rowStyle; + var colOrder = dataObj.colOrder; + var highLight = 0; + var reg = /(^|\s)invisibleRow(\s|$)/; + var tr, tds; + + for(var i = 0; i < len1; i++) { + tr = data[i][len2]; + if(colStyle) { + tds = tr.cells; + for(thPos in colOrder) { + if(!colOrder[thPos]) fdTableSort.removeClass(tds[thPos], colStyle); + else fdTableSort.addClass(tds[thPos], colStyle); + }; + }; + if(!identical) { + if(rowStyle && tr.className.search(reg) == -1) { + if(highLight++ & 1) fdTableSort.addClass(tr, rowStyle); + else fdTableSort.removeClass(tr, rowStyle); + }; + + // Netscape 8.1.2 requires the removeChild call or it freaks out, so add the line if you want to support this browser + // hook.removeChild(tr); + hook.appendChild(tr); + }; + }; + tr = tds = hook = null; + }, + getInnerText: function(el, allowBrTags) { + if (typeof el == "string" || typeof el == "undefined") return el; + if(el.innerText) return el.innerText; + var txt = '', i; + for(i = el.firstChild; i; i = i.nextSibling) { + if(allowBrTags && i.nodeName && i.nodeName == "BR") txt += "
"; + else if(i.nodeType == 3) txt += i.nodeValue; + else if(i.nodeType == 1) txt += fdTableSort.getInnerText(i); + }; + return txt; + }, + dateFormat: function(dateIn, favourDMY) { + var dateTest = [ + { 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 + { 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 + { 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 + ]; + var start, cnt = 0, numFormats = dateTest.length; + while(cnt < numFormats) { + start = (cnt + (favourDMY ? numFormats + 1 : numFormats)) % numFormats; + if(dateIn.match(dateTest[start].regExp)) { + res = dateIn.match(dateTest[start].regExp); + y = res[dateTest[start].y]; + m = res[dateTest[start].m]; + d = res[dateTest[start].d]; + if(m.length == 1) m = "0" + String(m); + if(d.length == 1) d = "0" + String(d); + if(y.length != 4) y = (parseInt(y) < 50) ? "20" + String(y) : "19" + String(y); + + return y+String(m)+d; + }; + cnt++; + }; + return 0; + }, + sortNumeric:function(a,b) { + var aa = a[fdTableSort.pos]; + var bb = b[fdTableSort.pos]; + if(aa == bb) return 0; + if(aa === "" && !isNaN(bb)) return -1; + if(bb === "" && !isNaN(aa)) return 1; + return aa - bb; + }, + sortText:function(a,b) { + var aa = a[fdTableSort.pos]; + var bb = b[fdTableSort.pos]; + if(aa == bb) return 0; + if(aa < bb) return -1; + return 1; + } +}; +})(); +fdTableSort.addEvent(window, "load", fdTableSort.initEvt); +fdTableSort.addEvent(window, "unload", fdTableSort.onUnload);