Сортировка HTML таблицы с использованием addEventListener в JavaScript - PullRequest
1 голос
/ 05 мая 2020

Я пытаюсь отсортировать HTML таблицу с помощью addEventListener в моем JavaScript, нажимая заголовок любого столбца таблицы. В основном это работает, но только в порядке возрастания или убывания. Он должен работать как тумблер; когда вы снова sh используете тот же заголовок столбца, порядок сортировки должен измениться по убыванию.

Я достаточно новичок, поэтому не знаю, как сделать функцию element.addEventListener для активации моих функций sortTable и reverseTable по очереди, нажимая тот же заголовок столбца.

Я думаю, проблема в этом блоке, поскольку addEventListener учитывает только функцию sortTable или функцию reverseTable, в зависимости от того, какая из них является последней в списке. В данном случае это функция reverseTable, поэтому она сортируется в порядке убывания и только один раз:

table.querySelectorAll('th') // get all the table header elements
  .forEach((element, columnNo)=>{ // add a click handler for each 
    element.addEventListener('click', event => {
        sortTable(table, columnNo); //call a function which sorts the table by a given column number
        reverseTable(table,columnNo); //call a function to sort in reverse order
    })
})

Весь код с данными таблицы находится здесь:

const table = document.querySelector('table'); //get the table to be sorted

table.querySelectorAll('th') // get all the table header elements
  .forEach((element, columnNo)=>{ // add a click handler for each 
    element.addEventListener('click', event => {
        sortTable(table, columnNo); //call a function which sorts the table by a given column number
		reverseTable(table,columnNo); //call a function to sort in reverse order
    })
})
  
  function sortTable(table, sortColumn){
  // get the data from the table cells
  const tableBody = table.querySelector('tbody')
  const tableData = table2data(tableBody);
  // sort the extracted data
  tableData.sort((a, b)=>{
    if(a[sortColumn] > b[sortColumn]){
      return 1;
    }
    return -1;
   })
   
   //put the sorted data back into the table
  data2table(tableBody, tableData);	
}

function reverseTable(table, sortColumn){
  // get the data from the table cells
  const tableBody = table.querySelector('tbody')
  const tableData = table2data(tableBody);
  // sort the extracted data
  tableData.reverse((a, b)=>{
    if(a[sortColumn] > b[sortColumn]){
      return -1;
    }
    return 1;
  })
  
  // put the sorted data back into the table
  data2table(tableBody, tableData);
}
   

// this function gets data from the rows and cells 
// within an html tbody element
function table2data(tableBody){
  const tableData = []; // create the array that'll hold the data rows
  tableBody.querySelectorAll('tr')
    .forEach(row=>{  // for each table row...
      const rowData = [];  // make an array for that row
      row.querySelectorAll('td')  // for each cell in that row
        .forEach(cell=>{
          rowData.push(cell.innerText);  // add it to the row data
        })
      tableData.push(rowData);  // add the full row to the table data 
    });
  return tableData;
}

// this function puts data into an html tbody element
function data2table(tableBody, tableData){
  tableBody.querySelectorAll('tr') // for each table row...
    .forEach((row, i)=>{  
      const rowData = tableData[i]; // get the array for the row data
      row.querySelectorAll('td')  // for each table cell ...
        .forEach((cell, j)=>{
          cell.innerText = rowData[j]; // put the appropriate array element into the cell
        })
      tableData.push(rowData);
    });
}
<table>
 <thead>
  <tr><th>Name</th><th>Surname</th><th>Age</th</tr>
 </thead>
 <tbody>
  <tr><td>John</td><td>Smith</td><td>62</td></tr>
  <tr><td>Dylan</td><td>Jones</td><td>37</td></tr>
  <tr><td>Alan</td><td>Shearer</td><td>55</td></tr>
  <tr><td>Ringo</td><td>Starr</td><td>52</td></tr>
 </tbody>
</table>

1 Ответ

0 голосов
/ 05 мая 2020

Итак, я решил вашу проблему, добавив атрибуты к тегам <th>, теперь они сохраняют свое состояние, и при следующем щелчке мы знаем, что делать, также я меняю функцию стрелки (name () => {}) на обычную функцию (имя функции () {}), чтобы получить доступ к this, чтобы узнать больше об их различиях, прочтите эту статью, так что вот ваш код, я надеюсь, что помог вам, и он работает должным образом

* EDIT: как @ user4642212, упомянутый в комментариях атрибуты данных - гораздо более удобный способ решить эту проблему, поэтому я отредактировал свой фактический код

const table = document.querySelector('table'); //get the table to be sorted

table.querySelectorAll('th') // get all the table header elements
  .forEach((element, columnNo) => { // add a click handler for each 
    element.addEventListener('click', function(event) {
      const isReverse = (this.dataset.reverse == 'true')
      this.dataset.reverse = !isReverse
      console.log(isReverse)
      if (isReverse) sortTable(table, columnNo); //call a function which sorts the table by a given column number
      else reverseTable(table, columnNo); //call a function to sort in reverse order
    })
  })

function sortTable(table, sortColumn) {
  // get the data from the table cells
  const tableBody = table.querySelector('tbody')
  const tableData = table2data(tableBody);
  // sort the extracted data
  tableData.sort((a, b) => {
    if (a[sortColumn] > b[sortColumn]) {
      return 1;
    }
    return -1;
  })

  //put the sorted data back into the table
  data2table(tableBody, tableData);
}

function reverseTable(table, sortColumn) {
  // get the data from the table cells
  const tableBody = table.querySelector('tbody')
  const tableData = table2data(tableBody);
  // sort the extracted data
  tableData.reverse((a, b) => {
    if (a[sortColumn] > b[sortColumn]) {
      return -1;
    }
    return 1;
  })

  // put the sorted data back into the table
  data2table(tableBody, tableData);
}


// this function gets data from the rows and cells 
// within an html tbody element
function table2data(tableBody) {
  const tableData = []; // create the array that'll hold the data rows
  tableBody.querySelectorAll('tr')
    .forEach(row => { // for each table row...
      const rowData = []; // make an array for that row
      row.querySelectorAll('td') // for each cell in that row
        .forEach(cell => {
          rowData.push(cell.innerText); // add it to the row data
        })
      tableData.push(rowData); // add the full row to the table data 
    });
  return tableData;
}

// this function puts data into an html tbody element
function data2table(tableBody, tableData) {
  tableBody.querySelectorAll('tr') // for each table row...
    .forEach((row, i) => {
      const rowData = tableData[i]; // get the array for the row data
      row.querySelectorAll('td') // for each table cell ...
        .forEach((cell, j) => {
          cell.innerText = rowData[j]; // put the appropriate array element into the cell
        })
      tableData.push(rowData);
    });
}
<table>
  <thead>
    <tr>
      <th data-reverse="true">Name</th>
      <th data-reverse="true">Surname</th>
      <th data-reverse="true">Age</th</tr>
  </thead>
  <tbody>
    <tr>
      <td>John</td>
      <td>Smith</td>
      <td>62</td>
    </tr>
    <tr>
      <td>Dylan</td>
      <td>Jones</td>
      <td>37</td>
    </tr>
    <tr>
      <td>Alan</td>
      <td>Shearer</td>
      <td>55</td>
    </tr>
    <tr>
      <td>Ringo</td>
      <td>Starr</td>
      <td>52</td>
    </tr>
  </tbody>
</table>
...