jQuery:按多列值对表进行排序

时间:2018-04-21 13:36:35

标签: jquery sorting html-table

我一直在努力解决这个问题,每次测试时我都会得到不同的结果。

JSFIDDLE

我有一个用于测试目的的基本表,其中3个条目有3个不同的标题,可按以下方式排序:名称,年龄,加入日期。

这是表格:

<table class="table">
<thead>
  <tr>
    <th scope="col">#</th>
    <th scope="col" id="firstName">name</th>
    <th scope="col" id="age">age</th>
    <th scope="col" id="date">date joined</th>
  </tr>
</thead>
<tbody>
  <tr>
    <th scope="row">1</th>
    <td class="firstName">Mark</td>
    <td>12</td>
    <td>12/02/2006</td>
  </tr>
  <tr>
    <th scope="row">2</th>
    <td class="firstName">Jacob</td>
    <td>30</td>
    <td>03/04/2018</td>
  </tr>
  <tr>
    <th scope="row">3</th>
    <td class="firstName">Larry</td>
    <td>22</td>
    <td>07/01/2009</td>
  </tr>
</tbody>

这是我的JS:

function sortTable(column) {
        var $tbody = $('.table tbody');
        $tbody.find('td.' + column).sort(function(a,b){ 
            var tda = $(a).find('td:eq(1)').text();
            var tdb = $(b).find('td:eq(1)').text();
                    // if a < b return 1
            return tda < tdb ? 1 
                   // else if a > b return -1
                   : tda > tdb ? -1 
                   // else they are equal - return 0    
                   : 0;           
        }).appendTo($tbody);
}

$('#firstName').click(function() {
    sortTable("firstName");
});
$('#age').click(function() {
    sortTable("age");
});
$('#date').click(function() {
    sortTable("date");
});

我想要实现的目标

我希望能够点击每个标题按照各自的内容对表格进行排序。因此,例如,当我点击名称时,它将按名称排序。当我点击年龄时,它将按年龄排序,当我点击加入日期时,它将按日期排序。

我也非常想学习,所以我会给出一个有很好评论的答案给予100分,这些评论可以解释我的情况。

谢谢。

function sortTable(column) {
  var $tbody = $('.table tbody');
  $tbody.find('td.' + column).sort(function(a, b) {
    var tda = $(a).find('td:eq(1)').text();
    var tdb = $(b).find('td:eq(1)').text();
    // if a < b return 1
    return tda < tdb ? 1
      // else if a > b return -1
      :
      tda > tdb ? -1
      // else they are equal - return 0    
      :
      0;
  }).appendTo($tbody);
}

$('#firstName').click(function() {
  sortTable("firstName");
});
$('#age').click(function() {
  sortTable("age");
});
$('#date').click(function() {
  sortTable("date");
});
@import 'https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css';
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col" id="firstName">name</th>
      <th scope="col" id="age">age</th>
      <th scope="col" id="date">date joined</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">1</th>
      <td class="firstName">Mark</td>
      <td>12</td>
      <td>12/02/2006</td>
    </tr>
    <tr>
      <th scope="row">2</th>
      <td class="firstName">Jacob</td>
      <td>30</td>
      <td>03/04/2018</td>
    </tr>
    <tr>
      <th scope="row">3</th>
      <td class="firstName">Larry</td>
      <td>22</td>
      <td>07/01/2009</td>
    </tr>
  </tbody>
</table>

2 个答案:

答案 0 :(得分:2)

目前,您正在排序<td>,实际上是一个单元格而不是行(<tr>)。

.sort的回调函数有2个参数。您需要比较2个参数和:

  1. 如果第一个参数应该先行,则返回负值。
  2. 如果第二个参数应该先行,则返回正值。
  3. 如果位置没有变化,则返回0.
  4. 您必须根据数据类型(数字,文本,日期)对数据进行比较。还使用了列的索引而不是文本,因为我觉得它更容易。

    function sortTable(column, type) {
    
      //Get and set order
      //Use -data to store wheater it will be sorted ascending or descending
      var order = $('.table thead tr>th:eq(' + column + ')').data('order');
      order = order === 'ASC' ? 'DESC' : 'ASC';
      $('.table thead tr>th:eq(' + column + ')').data('order', order);
    
      //Sort the table
      $('.table tbody tr').sort(function(a, b) {
      //                                 ^  ^
      //                                 |  | 
      //        The 2 parameters needed to be compared. 
      //        Since you are sorting rows, a and b are <tr>                                 
    
        //Find the <td> using the column number and get the text value.
        //Now, the a and b are the text of the <td>
        a = $(a).find('td:eq(' + column + ')').text();
        b = $(b).find('td:eq(' + column + ')').text();
    
        switch (type) {
          case 'text':
            //Proper way to compare text in js is using localeCompare
            //If order is ascending you can - a.localeCompare(b)
            //If order is descending you can - b.localeCompare(a);
            return order === 'ASC' ? a.localeCompare(b) : b.localeCompare(a);
            break;
          case 'number':
            //You can use deduct to compare if number.
            //If order is ascending you can -> a - b. 
            //Which means if a is bigger. It will return a positive number. b will be positioned first
            //If b is bigger, it will return a negative number. a will be positioned first
            return order === 'ASC' ? a - b : b - a;
            break;
          case 'date':
            var dateFormat = function(dt) {
              [m, d, y] = dt.split('/');
              return [y, m - 1, d];
            }
    
            //convert the date string to an object using `new Date`
            a = new Date(...dateFormat(a));
            b = new Date(...dateFormat(b));
    
            //You can use getTime() to convert the date object into numbers. 
            //getTime() method returns the number of milliseconds between midnight of January 1, 1970
            //So since a and b are numbers now, you can use the same process if the type is number. Just deduct the values.
            return order === 'ASC' ? a.getTime() - b.getTime() : b.getTime() - a.getTime();
            break;
        }
    
      }).appendTo('.table tbody');
    }
    
    $('#firstName').click(function() {
      sortTable(1, 'text');
    });
    $('#age').click(function() {
      sortTable(2, 'number');
    });
    $('#date').click(function() {
      sortTable(3, 'date');
    });
    table {
      font-family: arial, sans-serif;
      border-collapse: collapse;
      width: 100%;
    }
    
    td,
    th {
      border: 1px solid #dddddd;
      text-align: left;
      padding: 8px;
    }
    
    tr:nth-child(even) {
      background-color: #dddddd;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <table class="table">
      <thead>
        <tr>
          <th scope="col">#</th>
          <th scope="col" id="firstName">name</th>
          <th scope="col" id="age">age</th>
          <th scope="col" id="date">date joined</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td scope="row">1</td>
          <td class="firstName">Mark</td>
          <td>12</td>
          <td>12/02/2006</td>
        </tr>
        <tr>
          <td scope="row">2</td>
          <td class="firstName">Jacob</td>
          <td>30</td>
          <td>03/04/2018</td>
        </tr>
        <tr>
          <td scope="row">3</td>
          <td class="firstName">Larry</td>
          <td>22</td>
          <td>07/01/2009</td>
        </tr>
      </tbody>

答案 1 :(得分:1)

您可以对tr而不是td进行排序。

<强>样本

$('#firstName').click(function() {
  sortTable("firstName", this);
});
$('#age').click(function() {
  sortTable("age", this);
});
$('#date').click(function() {
  sortTable("date", this);
});

function sortTable(column, me) {
  var table = $(me).parents('table').eq(0),
    rows = table.find('tr:gt(0)').toArray().sort(doComparer($(this).index()))
  me.asc = !me.asc
  if (!me.asc) {
    rows = rows.reverse()
  }

  for (var i = 0; i < rows.length; i++) {
    table.append(rows[i])
  }
}

function doComparer(index) {
  return function(a, b) {
    a = getCellValue(a, index);
    b = getCellValue(b, index);
    return $.isNumeric(a) && $.isNumeric(b) ? a - b : a.toString().localeCompare(b)
  }
}

function getCellValue(row, index) {
  return $(row).children('td').eq(index).text()
}
th {
  cursor: pointer;
}
<link href="//stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col" id="firstName">name</th>
      <th scope="col" id="age">age</th>
      <th scope="col" id="date">date joined</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">1</th>
      <td class="firstName">Mark</td>
      <td>12</td>
      <td>12/02/2006</td>
    </tr>
    <tr>
      <th scope="row">2</th>
      <td class="firstName">Jacob</td>
      <td>30</td>
      <td>03/04/2018</td>
    </tr>
    <tr>
      <th scope="row">3</th>
      <td class="firstName">Larry</td>
      <td>22</td>
      <td>07/01/2009</td>
    </tr>
  </tbody>