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


Posted in Javascript onMay 26, 2015

本文实例讲述了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程序设计有所帮助。

Javascript 相关文章推荐
在JavaScript中实现命名空间
Nov 23 Javascript
jquery如何通过name名称获取当前name的value值
Dec 20 Javascript
一个小例子解释如何来阻止Jquery事件冒泡
Jul 17 Javascript
JavaScript电子时钟倒计时第二款
Jan 10 Javascript
JavaScript中eval函数的问题
Jan 31 Javascript
Webpack执行命令参数详解
Jun 17 Javascript
基于hover的用法实例(推荐)
Jul 04 Javascript
利用ES6实现单例模式及其应用详解
Dec 09 Javascript
关于layui flow loading占位图的实现方法
Sep 21 Javascript
Vue数据双向绑定底层实现原理
Nov 22 Javascript
JavaScript逻辑运算符相关总结
Sep 04 Javascript
Array.filter中如何正确使用Async
Nov 04 Javascript
js实现文本框选中的方法
May 26 #Javascript
javascript委托(Delegate)blur和focus用法实例分析
May 26 #Javascript
javascript删除元素节点removeChild()用法实例
May 26 #Javascript
JavaScript事件委托实例分析
May 26 #Javascript
JQuery选择器、过滤器大整理
May 26 #Javascript
javascript字符串与数组转换汇总
May 26 #Javascript
javascript获取文档坐标和视口坐标
May 26 #Javascript
You might like
最贵的咖啡是怎么产生的,它的风味怎么样?
2021/03/04 新手入门
动态新闻发布的实现及其技巧
2006/10/09 PHP
PHP+Mysql+jQuery实现发布微博程序 jQuery篇
2011/10/08 PHP
PHP异步调用socket实现代码
2012/01/12 PHP
php 中文字符串首字母的获取函数分享
2013/11/04 PHP
php foreach正序倒序输出示例代码
2014/07/01 PHP
PHP清除字符串中所有无用标签的方法
2014/12/01 PHP
WampServer下安装多个版本的PHP、mysql、apache图文教程
2015/01/07 PHP
php实现和c#一致的DES加密解密实例
2017/07/24 PHP
jQuery 性能优化指南 (1)
2009/05/21 Javascript
在VS2008中使用jQuery智能感应的方法
2010/12/30 Javascript
js弹出窗口之弹出层的小例子
2013/06/17 Javascript
jquery移动节点实例
2015/01/14 Javascript
jQuery中unwrap()方法用法实例
2015/01/16 Javascript
简易的JS计算器实现代码
2016/10/18 Javascript
vue中mint-ui环境搭建详细介绍
2017/04/06 Javascript
详解vue数据渲染出现闪烁问题
2017/06/29 Javascript
vue 系列——vue2-webpack2框架搭建踩坑之路
2017/12/22 Javascript
vue实现购物车小案例
2019/09/27 Javascript
jQuery实现鼠标放置名字上显示详细内容气泡提示框效果的方法分析
2020/04/04 jQuery
JavaScript实现简单动态表格
2020/12/02 Javascript
JavaScript中跨域问题的深入理解
2021/03/04 Javascript
pydev使用wxpython找不到路径的解决方法
2013/02/10 Python
Python编程实现数学运算求一元二次方程的实根算法示例
2017/04/02 Python
详解python实现读取邮件数据并下载附件的实例
2017/08/03 Python
Django中使用MySQL5.5的教程
2019/12/18 Python
找到不普通的东西:Bonanza
2016/10/20 全球购物
泰国Robinson百货官网:购买知名品牌的商品
2020/02/08 全球购物
计算机网络专业个人的自我评价
2013/10/17 职场文书
五年后的职业生涯规划
2014/03/04 职场文书
组织鉴定材料
2014/06/02 职场文书
三严三实民主生活会发言稿
2014/10/13 职场文书
2015年部门工作总结范文
2015/03/31 职场文书
2015年重阳节活动主持词
2015/07/30 职场文书
python 如何在 Matplotlib 中绘制垂直线
2021/04/02 Python
nginx日志格式分析和修改
2022/04/28 Servers