首页 > 编程 > JavaScript > 正文

JavaScript对表格或元素按文本,数字或日期排序的方法

2019-11-20 12:24:23
字体:
来源:转载
供稿:网友

本文实例讲述了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);    };  else    AddEvent = function (elem, eventType, func) {      elem['on' + eventType] = func;    };  AddEvent(elem, eventType, func);};// Sort methods/algorithms attributed:var SortTable = function (tbl, col) {  // could be called directly  SortElements(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 text    var 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 .data    var 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 well    return 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 child    aChild = 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 previously      parent.prevSort = (parent.prevSort == 'asc') ? 'desc' : 'asc';    } else { // sorting by any other column      parent.prevCol = colIndex;      parent.prevSort = 'asc';    }  } else {    // sorting for the 1st time or by a different tag    parent.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 header      SortElements(a, b, c, d);    }  }  // add sorting to table headers  for ( 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 row  var 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 present        cell.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 row  var 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 02    return $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 year    sParsed = (new Date().getFullYear()) + sParsed;  }  if (sParsed.charAt(sParsed.length - 1) == '/') {    // if no date, assume the 1st of the month    sParsed += '01';  }  // should end up with 10 characters..  return ( sParsed.length == 10 ) ? sParsed : '';};

希望本文所述对大家的javascript程序设计有所帮助。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表