如何水平排序表

问题描述 投票:0回答:2

我试图水平排序表。

排序包括单击标题,因此元素应该排序。

我试过下面的代码

但它没有正确排序。什么是适当的解决方案,没有任何插件?

$('th').click(function() {
  var rows = $('tr');

  rows.eq(0).find('td').sort(function(a, b) {
    return $.text([a]) > $.text([b]) ? 1 : -1;
  }).each(function(newIndex) {
    var originalIndex = $(this).index();
    rows.each(function() {
      var td = $(this).find('td');
      if (originalIndex !== newIndex)
        td.eq(originalIndex).insertAfter(td.eq(newIndex));
    });
  });
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myTable">
  <tr>
    <th>Product</th>
    <td>Golden Watch</td>
    <td>Silver Watch</td>
    <td>Car 2018</td>
    <td>Wooden Table</td>
    <td>Sport Car 2019</td>
    <td>Perfume</td>
    <td>Car 2010</td>
    <td>Piano</td>


  </tr>
  <tr>
    <th>Price($)</th>
    <td>1000</td>
    <td>600</td>
    <td>60000</td>
    <td>50</td>
    <td>100000</td>
    <td>100</td>
    <td>10000</td>
    <td>250000</td>

  </tr>
  <tr>
    <th>Origin Country</th>
    <td>Switzerland</td>
    <td>USA</td>
    <td>Germany</td>
    <td>Sweden</td>
    <td>Italy</td>
    <td>France</td>
    <td>England</td>
    <td>Austria</td>

</table>
jquery
2个回答
1
投票

这是我提出的解决方案的版本。

  1. 它做的第一件事是从表中获取所有数据并将其加载到变量中,因此我们只需要从页面中获取所有数据一次。
  2. 它接下来要做的是创建click事件监听器。我把它作为代表,因为我一起替换tr元素。 事件监听器所做的第一件事就是检查哪些th被其innerHTML所点击。如果它是字符串字段之一,我在字符串上做了localeCompare。否则,如果它是数字价格,我只是减去它们进行排序。 我做的最后一件事是用新行替换表的全部内容。新行是从已排序的数据生成的。我选择用生成的新行替换表的全部内容,因为新行是在DOM片段中构造的,并且此时与DOM的唯一接触点是表的所有子项的单个替换。因此,它比一次更换一行或每次更新每行的一列更具性能。

var $tableRows = $('#myTable tr');
var preloadData = $tableRows.first().find('td').map(function(index){
  return {
    product: $tableRows.eq(0).find('td').eq(index).html().trim()
    , price: parseInt($tableRows.eq(1).find('td').eq(index).html().trim(), 10)
    , originCountry: $tableRows.eq(2).find('td').eq(index).html().trim()
  }
}).get();

$(document).on('click', '#myTable tr', function(e){
  var sortDesc = e.target.classList.contains('asc');
  var sortingRow
  
  if (e.target.innerHTML === 'Product') {
    sortingRow = 0;
    
    preloadData.sort(function(a, b){
      if (sortDesc) return b.product.localeCompare(a.product);
      
      return a.product.localeCompare(b.product);
    });
  } else if (e.target.innerHTML === 'Price($)') {
    sortingRow = 1;
    
    preloadData.sort(function(a, b){
      if (sortDesc) return b.price - a.price;
      
      return a.price - b.price;
    });
  } else {
    sortingRow = 2;
    
    preloadData.sort(function(a, b){
      if (sortDesc) return b.originCountry.localeCompare(a.originCountry);
      
      return a.originCountry.localeCompare(b.originCountry);
    });
  }
  
  $('#myTable').html(
    preloadData.reduce(function($rows, columnData, index){
      if (index < 1) {
        $rows.eq(0).append('<th>Product</th>');
        $rows.eq(1).append('<th>Price($)</th>');
        $rows.eq(2).append('<th>Origin Country</th>');
        
        if (!sortDesc) $rows.eq(sortingRow).find('th').addClass('asc');
      }
      
      $rows.eq(0).append('<td>'+ columnData.product +'</td>');
      $rows.eq(1).append('<td>'+ columnData.price +'</td>');
      $rows.eq(2).append('<td>'+ columnData.originCountry +'</td>');
      
      return $rows;
    }, $('<tr><tr><tr>'))
  );
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myTable">
  <tr>
    <th>Product</th>
    <td>Golden Watch</td>
    <td>Silver Watch</td>
    <td>Car 2018</td>
    <td>Wooden Table</td>
    <td>Sport Car 2019</td>
    <td>Perfume</td>
    <td>Car 2010</td>
    <td>Piano</td>


  </tr>
  <tr>
    <th>Price($)</th>
    <td>1000</td>
    <td>600</td>
    <td>60000</td>
    <td>50</td>
    <td>100000</td>
    <td>100</td>
    <td>10000</td>
    <td>250000</td>

  </tr>
  <tr>
    <th>Origin Country</th>
    <td>Switzerland</td>
    <td>USA</td>
    <td>Germany</td>
    <td>Sweden</td>
    <td>Italy</td>
    <td>France</td>
    <td>England</td>
    <td>Austria</td>

</table>

编辑:在按升序排序的行上添加asc类的设置。如果它第二次被点击,它将翻转以排序降序。


0
投票

这是一种通用的方法,它不关心标记的行数或标记。

它首先创建rowData数组,其中每个子数组是具有原始列号和每个单元格的文本的对象数组。创造这个;将数据属性添加到每个单元格,以便它知道它是用于保持列关系的永久列号

这些是首先进行排序的,因此可以创建一个对象来存储具有新排序索引的原始列号。然后随着每行细胞的排序

// store row data arrays for easy sorting
var rowData = $('tr').map(function(rIdx, row) {
  return [$(row).children('td').map(function(cIdx, cell) {
    // store col # on each cell to use later for matching column sort order
    $(cell).data('col', cIdx + 1);
    // these objects used to keep original column numbers with sorted text
    return {
      col: cIdx + 1,
      text: cell.textContent
    }
  }).get()];
}).get();

var $th=$('#myTable th'),
  $rows = $('#myTable tr');


$th.click(function() {
   var $cell = $(this),
   rIdx = $cell.parent().index(),
   isSorted = $cell.hasClass('sorted'),
   dir = isSorted ? $cell.hasClass('asc') ? 'dsc':'asc' :'asc';
   
   $cell.removeClass('asc dsc').addClass('sorted '+ dir);  
  
   $th.not(this).removeClass('sorted asc dsc');  
 
  $rows.each(function() {
    var sortedCells = $(this).children('td').sort(rowCellSorter(rIdx, dir));
    $(this).append(sortedCells)
  });
});

function rowCellSorter(rIdx, dir) {
  var sortOrder = getSorterOrder(rIdx, dir);
  return function(a, b) {
    var aCol = $(a).data('col'),
      bCol = $(b).data('col')
    return sortOrder[aCol] - sortOrder[bCol]
  }
}

function getSorterOrder(rIdx, dir) {
  var dataRow = rowData[rIdx].slice().sort(dataRowSorter);
  
  if(dir === 'dsc'){
      dataRow.reverse()
  }
  // object with column num as keys, sort index as values
  return dataRow.reduce(function(a, c, i) {
    a[c.col] = i;
    return a;
  }, {});

}

function dataRowSorter(a, b) {
  if (isNaN(a.text)) { // text sort
    return a.text.localeCompare(b.text)
  } else { // num sort
    return a.text - b.text
  }
}
.asc:after{
  content:' > '
}

.dsc:after{
  content:' < '
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myTable">
  <tr>
    <th>Product</th>
    <td>Golden Watch</td>
    <td>Silver Watch</td>
    <td>Car 2018</td>
    <td>Wooden Table</td>
    <td>Sport Car 2019</td>
    <td>Perfume</td>
    <td>Car 2010</td>
    <td>Piano</td>


  </tr>
  <tr>
    <th>Price($)</th>
    <td>1000</td>
    <td>600</td>
    <td>60000</td>
    <td>50</td>
    <td>100000</td>
    <td>100</td>
    <td>10000</td>
    <td>250000</td>

  </tr>
  <tr>
    <th>Origin Country</th>
    <td>Switzerland</td>
    <td>USA</td>
    <td>Germany</td>
    <td>Sweden</td>
    <td>Italy</td>
    <td>France</td>
    <td>England</td>
    <td>Austria</td>

</table>
© www.soinside.com 2019 - 2024. All rights reserved.