来源于:http://www.frequency-decoder.com/demo/table-sort-revisited/
table排序代码:
(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
@*/
//fdTableSort.addEvent(window, "load",fdTableSort.initEvt);
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]);
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.title = "Sort on \u201c" + thtext + "\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;
if(cb.indexOf(".") != -1) {
var split = cb.split(".");
func = window;
for(var i = 0, f; f = split[i]; i++) {
if(f in func) {
func = func[f];
} else {
func = "";
break;
};
};
} else if(cb + tblId in window) {
func = window[cb + tblId];
} else if(cb in window) {
func = window[cb];
};
if(typeof func == "function") { func(tblId, fdTableSort.tableCache[tblId].thList); };
func = null;
},
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++) {