Как отсортировать таблицу по горизонтали

Я пытаюсь отсортировать таблицу по горизонтали.

Сортировка состоит из щелчка по заголовку, поэтому элементы должны быть отсортированы.

Я пробовал код ниже

Но он не сортирует его должным образом. Какое адекватное решение для этого, без каких-либо плагинов?

$('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>

Сохранить те же отношения столбцов? Если да, то какой должна быть основная сортировка... верхняя строка?

charlietfl 09.04.2019 23:48

Чтобы отсортировать числа, вам нужно сделать их числовыми, а не строковыми, поскольку 5000 больше 10000 в алфавитном порядке.

mplungjan 09.04.2019 23:48

@charlietfl Да, те же самые отношения. Он должен отсортировать строку с щелчком по заголовку.

Barrett 09.04.2019 23:49
Как конвертировать HTML в PDF с помощью jsPDF
Как конвертировать HTML в PDF с помощью jsPDF
В этой статье мы рассмотрим, как конвертировать HTML в PDF с помощью jsPDF. Здесь мы узнаем, как конвертировать HTML в PDF с помощью javascript.
0
3
159
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот версия решения, которое я придумал.

  1. Первое, что он делает, это берет все данные из таблицы и загружает их в переменную, поэтому нам нужно только один раз получить все эти данные со страницы.
  2. Следующее, что он делает, это создает прослушиватель событий щелчка. Я сделал его делегатом, так как я заменяю все элементы tr вместе.
    1. Первое, что делает прослушиватель событий, — это проверяет, какой th был нажат с помощью его innerHTML. Если это одно из строковых полей, я сделал localeCompare для строк. В противном случае, если это числовая цена, я просто вычел их для сортировки.
    2. Последнее, что я делаю, это заменяю все содержимое таблицы новыми строками. Новые строки генерируются из отсортированных данных. Я решил заменить все содержимое таблицы сгенерированными новыми строками, поскольку новые строки создаются во фрагменте 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 в строку, отсортированную по возрастанию. Если щелкнуть ее второй раз, она перевернется для сортировки по убыванию.

Вот общий подход, который не заботится о том, сколько строк или какова маркировка.

Сначала он создает массив 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>

Другие вопросы по теме