本文实例讲述了JavaScript对表格或元素按文本,数字或日期排序的方法。分享给大家供大家参考。具体实现方法如下:
// Sorting table columns correctly by text, number or date. There are other // versions, plugins, etc., for this but they either are restricted to specific // date formats, or require EVERY row-element to be given a sort attribute; mine // can handle many different date and number formats, and even allows for specific // cells that may not conform to the overall date/number format for that column. // My version also enables sorting of element hierarchies: such as a DIV containing // P-paragraphs and SPANs - this could even be an image-gallery containing prices // or dates within spans. Very efficient as well!!// Example: andrew.dx.am/sortgallerydel.html// AddSortToTables(); will make the table headers clickable, to sort columns in // ascending or descending order, for any tables with class="sortIt".// SortTable(tbl, col); will sort the table (tbl is an id or table object) by // the supplied column index (indexed from 0) in ascending or descending order.// AddSortByDate(tbl, col, dateMask); enables sorting of a column by date, // specified by a date-mask such as "dd-mmm-yy".// AddSortByNumber(tbl, col); enables sorting of a column by number. This assumes a // period . as the decimal separator (if present); it ignores any other non-numeric // characters.// SortElements(parentEl, childTag, colTag, colIndex); will sort (non-table) // elements in ascending or descending order. For example, an UL containing LIs // and SPANs. colIndex specifies which span to sort; there may be more than one in // the LI (0 indexed).// Example: SortElements("divid", "p", "span", 2);// 3rd span within each paragraph.//// AddSortByDate2(parentEl, childTag, colTag, colIndex, dateMask); and // AddSortByNumber2(parentEl, childTag, colTag, colIndex)// provide the same feature-set as AddSortByDate and AddSortByNumber does // for tables, but for element hierarchies.// If there are dates or numbers in a column (or element) which don"t meet the // date-mask or number formatting necessary to sort correctly, then these individual // elements can be given the attribute "sort" and they will still sort correctly!// For example, with a date column <td sort="2012/12/20"> will still sort a // cell correctly. (This format "YYYY/MM/DD" will be converted into a Date() object.)var MonthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];var DayNames = [ "Sunday", "Monday", "Tueday", "Wednesday", "Thursday", "Friday", "Saturday" ];var ShortMths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];var ShortDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];var AddEvent = function (elem, eventType, func) {// Helper function.if ( elem.addEventListener )AddEvent = function (elem, eventType, func) {elem.addEventListener(eventType, func, false);};else if ( elem.attachEvent )AddEvent = function (elem, eventType, func) {elem.attachEvent("on" + eventType, func);};elseAddEvent = function (elem, eventType, func) {elem["on" + eventType] = func;};AddEvent(elem, eventType, func);};// Sort methods/algorithms attributed:var SortTable = function (tbl, col) {// could be called directlySortElements(tbl, "tr", "td", col);};var SortElements = function (parentEl, childTag, colTag, colIndex) {// example use: SortElements("table1","tr","td",2)// or SortElements("list1","li")// or SortElements("divName","p","span",3)var i, j, cTags = {}, startAt = 0, childLen, aChild, elem,sortBy, content, elems = [], sortedLen, frag, hdrsLen, hdr;var parent = (typeof parentEl === "string") ? document.getElementById(parentEl) : parentEl;var AscText = function (a, b) { // sort() by .data as textvar x = a.data, y = b.data,xNum = parseFloat(x), yNum = parseFloat(y);// check if each begin with a number..if ( !isNaN(xNum) && !isNaN(yNum) && (xNum - yNum) )return xNum - yNum;return ((x < y) ? -1 : ((x > y) ? 1 : 0));};var DescText = function (a, b) { // sort() by .datavar x = a.data, y = b.data,xNum = parseFloat(x), yNum = parseFloat(y);// check if each begin with a number..if ( !isNaN(xNum) && !isNaN(yNum) && (yNum - xNum) )return yNum - xNum;return ((x > y) ? -1 : ((x < y) ? 1 : 0));};var AscNum = function (a, b) { // used with dates as wellreturn a.data - b.data;};var DescNum = function (a, b) {return b.data - a.data;};if (parent.nodeName.toLowerCase() == "table") {if ( childTag == "tr" ) {sortBy = parent.rows[0].cells[colIndex].sortBy || "text";}parent = parent.tBodies[0] || parent;if ( parent.rows[0].cells[0].nodeName.toLowerCase() == "th" ) {startAt = 1;}}cTags = parent.getElementsByTagName(childTag);if ( typeof colIndex == "undefined" ) {sortBy = "text"; // sort simple lists or paragraphs as text}for (i = startAt, childLen = cTags.length; i < childLen; i++) {// ..go forward examining each childaChild = cTags[i];elem = (colTag) ? aChild.getElementsByTagName(colTag)[colIndex] : aChild;if (elem) {if ( !sortBy ) { // sorting non-table columns..sortBy = (typeof elem.numberValue != "undefined") ? "number" : ((typeof elem.dateValue != "undefined") ? "date" : "text");}switch (sortBy) {// You can supply "sort" attributes to enable sorting of numbers, etc.// For example, <td sort="2011/02/12"> for a date.case "text":content = (elem.getAttribute("sort") || elem.firstChild.nodeValue).toLowerCase();break;case "number":content = elem.numberValue;break;case "date":content = elem.dateValue;break;default:content = (elem.getAttribute("sort") || elem.firstChild.nodeValue).toLowerCase();break;}j = elems.length;if ( !aChild.id ) aChild.id = "tempSortID" + j;elems[j] = { data: content, tempID: aChild.id };}}// The following will determine if the table/etc has already been sorted // by the same column or tag. If so, it will sort in ascending or descending // order. It creates custom element properties to the parent element to // remember the previous sort details.if ( typeof colIndex == "undefined" ) colIndex = 0;if ( parent.prevTag && parent.prevTag == ((typeof colTag == "undefined") ? childTag : colTag) ) {if (parent.prevCol == colIndex) {// sorting by the same column as previouslyparent.prevSort = (parent.prevSort == "asc") ? "desc" : "asc";} else { // sorting by any other columnparent.prevCol = colIndex;parent.prevSort = "asc";}} else {// sorting for the 1st time or by a different tagparent.prevTag = ((typeof colTag == "undefined") ? childTag : colTag);parent.prevCol = colIndex;parent.prevSort = "asc";}if ( parent.prevSort === "desc" ) {// "desc" WILL BE the previous sort order..switch (sortBy) {case "text": elems.sort(DescText); break;case "number": elems.sort(DescNum); break;case "date": elems.sort(DescNum); break;default: elems.sort(DescText); break;}} else {switch (sortBy) {case "text": elems.sort(AscText); break;case "number": elems.sort(AscNum); break;case "date": elems.sort(AscNum); break;default: elems.sort(AscText); break;}}frag = document.createDocumentFragment();for (i = 0, sortedLen = elems.length; i < sortedLen; i++) {elem = document.getElementById(elems[i].tempID);frag.appendChild(elem);if ( (elem.id).substr(0,10) == "tempSortID" )elem.removeAttribute("id");}parent.appendChild(frag);elems = null;return parent.prevSort; // not currently used};var AddSortToTables = function () {// ..if table has class-name "sortIt"var tables = document.getElementsByTagName("table"), i, j, tblLen, tbl, hdrs, hdrsLen;function PreserveSortScope(a,b,c,d) {return function () {// assign the SortElements fn. to a table headerSortElements(a, b, c, d);}}// add sorting to table headersfor ( i = 0, tblLen = tables.length; i < tblLen; i++ ) { tbl = tables[i];if ( tbl.className.indexOf("sortIt") + 1) {hdrs = tbl.getElementsByTagName("th");if ( hdrs ) {for ( j = 0, hdrsLen = hdrs.length; j < hdrsLen; j++ ) {AddEvent(hdrs[j],"click",PreserveSortScope(tbl,"tr","td",j));// if there"s no title already, add "Click to sort"if ( !hdrs[j].title ) hdrs[j].setAttribute("title","Click to sort");}}}}};var AddSortByDate = function (tbl, col, dateMask) {// Input: the table name (or object), a column index (or array) // and a date mask ("dd-mmm-yy")// Adds a sortBy = "date" property to the first row// will ignore the first row, assuming it is a header rowvar i, rLen, cell;while ( col.length ) AddSortByDate(tbl,col.pop(),dateMask);if ((col instanceof Array) || isNaN(col)) return;var tbl = (typeof tbl === "string") ? document.getElementById(tbl) : tbl;tbl.rows[0].cells[col].sortBy = "date";AddSortByDate2(tbl, "tr", "td", col, dateMask);};var AddSortByDate2 = function (parentEl, childTag, colTag, colIndex, dateMask) {var kids, startAt = 0, i, rLen, cell;var parent = (typeof parentEl === "string") ? document.getElementById(parentEl) : parentEl;if ( parent.nodeName.toLowerCase() == "table" ) {parent = parent.tBodies[0] || parent;startAt = ( parent.rows[0].cells[0].nodeName.toLowerCase() == "th" ) * 1;}kids = parent.getElementsByTagName(childTag);for ( i = startAt, rLen = kids.length; i < rLen; i++) {cell = kids[i].getElementsByTagName(colTag)[colIndex];if (cell) {if ( typeof cell.numberValue != "undefined" ) delete cell.numberValue;// the above enables switching from a number to a date sort // (although v. unlikely)if (cell.getAttribute("sort")) {// use sort attribute if presentcell.dateValue = new Date(cell.getAttribute("sort"));} else {cell.dateValue = new Date(StringToDate(cell.firstChild.nodeValue, dateMask));}if (cell.dateValue.toString() == "NaN" || cell.dateValue.toString() == "Invalid Date") {cell.dateValue = 0;} }}};var AddSortByNumber = function (tbl, col) {// col is a column index or array of indices// will ignore the first row, assuming it is a header rowvar i, rLen, cell, tempNum;while ( col.length ) AddSortByNumber(tbl,col.pop());if ((col instanceof Array) || isNaN(col)) return;tbl = (typeof tbl === "string") ? document.getElementById(tbl) : tbl;tbl.rows[0].cells[col].sortBy = "number";AddSortByNumber2(tbl,"tr","td",col);};var AddSortByNumber2 = function (parentEl, childTag, colTag, colIndex) {var kids, startAt = 0, i, rLen, cell, tempNum;var parent = (typeof parentEl === "string") ? document.getElementById(parentEl) : parentEl;if ( parent.nodeName.toLowerCase() == "table" ) {parent = parent.tBodies[0] || parent;startAt = (parent.rows[0].cells[0].nodeName.toLowerCase() == "th") * 1;}kids = parent.getElementsByTagName(childTag);for (i = startAt, rLen = kids.length; i < rLen; i++) {cell = kids[i].getElementsByTagName(colTag)[colIndex];if (cell) {if ( typeof cell.dateValue != "undefined" ) delete cell.dateValue;// the above enables switching from a date to a number sort// (although v. unlikely)tempNum = cell.getAttribute("sort") || cell.firstChild.nodeValue;tempNum = tempNum.replace(/[^0-9.-]/g, "");cell.numberValue = parseFloat(tempNum);if (isNaN(cell.numberValue)) cell.numberValue = 0.0;}}};var StringToDate = function (sDate, sFormat, cutOff) {// Input: a date value as a string, it"s format as a string e.g. "dd-mmm-yy"// Optional: a cutoff (integer) for 2 digit years.// If no "d" appears in the format string then the 1st of the month is assumed.// If the year is 20 and the cut-off is 30 then the value will be converted // to 2020; if the year is 40 then this will be converted to 1940.// If no cut-off is supplied then "20" will be pre-pended to the year (YY).// Output: a string in the format "YYYY/MM/DD" or ""// Will not attempt to convert certain combinations e.g. DMM, MDD, DDM, YYYYD.var sParsed, fndSingle;// sParsed will be constructed in the format "YYYY/MM/DD"sDate = sDate.toString().toUpperCase();sFormat = sFormat.toUpperCase();if (sFormat.search(/MMMM|MMM/) + 1) { // replace Mar/March with 03, etc.sDate = sDate.replace(new RegExp("(" + ShortMths.join("|") + ")[A-Z]*", "gi"),function (m) {var i = ShortMths.indexOf(m.charAt(0).toUpperCase() + m.substr(1, 2).toLowerCase()) + 1;return ((i < 10) ? "0" + i : "" + i).toString();});sFormat = sFormat.replace(/MMMM|MMM/g, "MM");}if (sFormat.search(/DDDD|DDD/) + 1) { // replace Tue/Tuesday, etc. with ""sDate = sDate.replace(new RegExp("(" + ShortDays.join("|") + ")[A-Z]*", "gi"),"");sFormat = sFormat.replace(/DDDD|DDD/g, "");}sDate = sDate.replace(/(^|D)(d)(?=D|$)/g, function($0, $1, $2) {// single digits 2 with 02return $1 + "0" + $2;});sFormat = sFormat.replace(/(^|[^DMY])(D|M)(?=[^DMY]|$)/g, function($0, $1, $2){return $1 + $2 + $2; // replace D or M with DD and MM});// are there still single Ds or Ms?fndSingle = sFormat.search(/(^|[^D])D([^D]|$)|(^|[^M])M([^M]|$)/)+1;if ( fndSingle ) return ""; // do not attempt to parse, for example, "DMM"sFormat = sFormat.replace(/(^|[^Y])(YY)(?=[^Y]|$)/g, function($0, $1, $2, index) {var tempDate = sDate.substr(0, index + 1);tempDate += (cutOff) ? ((parseInt(sDate.substr(index + 1, 2),10) > cutOff) ? "19" : "20") : "20";tempDate += sDate.substr(index + 1);sDate = tempDate;return $1 + $2 + $2;});sParsed = ("YYYY/MM/DD").replace(/YYYY|MM|DD/g, function(m){return (sFormat.indexOf(m) + 1) ? sDate.substr(sFormat.indexOf(m), m.length) : "";});if (sParsed.charAt(0) == "/") {// if no year specified, assume the current yearsParsed = (new Date().getFullYear()) + sParsed;}if (sParsed.charAt(sParsed.length - 1) == "/") {// if no date, assume the 1st of the monthsParsed += "01";}// should end up with 10 characters..return ( sParsed.length == 10 ) ? sParsed : "";};希望本文所述对大家的javascript程序设计有所帮助。