Сортировать html-таблицу по алфавиту и по номерам

Следующий JavaScript работает в большинстве случаев (в алфавитном порядке), и он должен игнорировать новые строки или пробелы, а также должен игнорировать внутренний HTML. Однако при сортировке столбца 2 он не соответствует логической нумерации 1, 2, 14, 17 ..., поскольку сначала сортирует 1, затем 2 и т. д. Неверно в числовом виде.

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

window.onload = function() {
  document.querySelectorAll('th').forEach((element) => { // Table headers
    element.addEventListener('click', function() {
      let table = this.closest('table');

      // If the column is sortable
      if (this.querySelector('span')) {
        let order_icon = this.querySelector('span');
        let order = encodeURI(order_icon.innerHTML).includes('%E2%86%91') ? 'desc' : 'asc';
        let separator = '-----'; // Separate the value of it's index, so data keeps intact

        let value_list = {}; // <tr> Object
        let obj_key = []; // Values of selected column

        let string_count = 0;
        let number_count = 0;

        // <tbody> rows
        table.querySelectorAll('tbody tr').forEach((line, index_line) => {
          // Value of each field
          let key = line.children[element.cellIndex].textContent.toUpperCase().trim();

          // Check if value is date, numeric or string
          if (line.children[element.cellIndex].hasAttribute('data-timestamp')) {
            // if value is date, we store it's timestamp, so we can sort like a number
            key = line.children[element.cellIndex].getAttribute('data-timestamp');
          } else if (key.replace('-', '').match(/^[0-9,.]*$/g)) {
            number_count++;
          } else {
            string_count++;
          }

          value_list[key + separator + index_line] = line.outerHTML.replace(/(\t)|(\n)/g, ''); // Adding <tr> to object
          obj_key.push(key + separator + index_line);
        });
        if (string_count === 0) { // If all values are numeric
          obj_key.sort(function(a, b) {
            return a.split(separator)[0] - b.split(separator)[0];
          });
        } else {
          obj_key.sort();
        }

        if (order === 'desc') {
          obj_key.reverse();
          order_icon.innerHTML = '&darr;';
        } else {
          order_icon.innerHTML = '&uarr;';
        }

        let html = '';
        obj_key.forEach(function(chave) {
          html += value_list[chave];
        });
        table.getElementsByTagName('tbody')[0].innerHTML = html;
      }
    });
  });
}
<table border = "1" id = "myTable2" class = "resize-table-font">
  <thead>
    <tr>
      <th>
        <p align = "center">name <span>&uarr;</span></p>
      </th>
      <th>
        <p align = "center">ref <span>&uarr;</span></p>
      </th>
    </tr>
  </thead>
  <tr>
    <td>

      1</td>
    <td>
      (book 
      3: 16)</td>

  </tr>
  <tr>
    <td>
      22</td>
    <td>
      (book 3: 16)</td>


  </tr>
  <tr>
    <td>

      book</td>

    <td>
      (book 2: 1-3)</td>
  </tr>
  <tr>
    <td>
      2</td>

    <td>
      (book 19: 12)</td>
  </tr>
  <tr>
    <td>
      how</td>
    <td>
      (book 19: 10, 12)</td>

  </tr>
  <tr>
    <td>
      when</td>
    <td>
      (book 19: 28; 21: 31)؟</td>

  </tr>
  <tr>
    <td>
      love</td>
    <td>
      (book 19: 30; 21: 31)؟</td>

  </tr>
  <tr>
    <td>
      3</td>
    <td>
      (book 10: 41; 14: 6, 7; 15: 3)</td>

  </tr>
  <tr>
    <td>
      tg</td>
    <td>
      (book 21: 30)</td>

  </tr>
  <tr>
    <td>

      web</td>
    <td>
      (book 19: 26; 21: 30)</td>

  </tr>
  <tr>
    <td>
      internet</td>
    <td>
      (book 15: 32; 19: 7)</td>

  </tr>
  <tr>
    <td>
      far4</td>
    <td>
      (book 19: 13)</td>

  </tr>
  <tr>
    <td>
      far3</td>
    <td>
      (book 21: 32)</td>


  </tr>
  <tr>
    <td>
      far33</td>
    <td>
      (book 20: 8; 21: 27)</td>

  </tr>
</table>

Ваша вложенность недействительна (единственный допустимый дочерний элемент <tr> — это <th> или <td> (у вас есть хотя бы один <span>, обертывающий <th>); элемент <font> устарел с HTML 4.1, align, cellpadding и cellspacing Атрибуты должны управляться с помощью CSS (text-align, padding и border-spacing соответственно). Я еще не просматривал JavaScript, но настоятельно рекомендую вам привести в порядок и исправить свой HTML.

David Thomas 02.04.2023 13:38

Похоже, недопустимое вложение - это проблема, о которой упоминал Дэвид. Вы оборачиваете детей внутри tr в интервале. и код js зацикливается, чтобы определить сортировку, поэтому будет учитываться, что в tr есть только один дочерний элемент. Очистите свой код с помощью правильной вложенности.

CodeThing 02.04.2023 13:53

Спасибо за ответ, я удалил все остальные теги и диапазоны (кроме тех, что в заголовке, которые необходимы для запуска js-скрипта, но все еще имеют ту же проблему с сортировкой. Или, если есть более простой js-код, он может быть используется для сортировки одного и того же контента.

Mike 02.04.2023 15:49
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
142
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Ниже приведен фрагмент кода, который сортирует вашу таблицу на основе текстового содержимого ячеек в столбце таблицы, который необходимо отсортировать.

Я попытался изменить ваш существующий код, но многое нужно было переопределить. Однако основная структура остается, и то, как вы пытались отсортировать таблицу, все еще на месте. Я использовал более описательные имена переменных, чтобы упростить отслеживание/отладку и интеграцию обратно в исходный код.

window.onload = function() {
  // Table headers
  document.querySelectorAll('th').forEach((elem) => {
    elem.addEventListener('click', headerClick);
  });
};

function headerClick(e) {
  // 'this' keyword can be used. 'e.currentTarget' makes
  // it easier to interpret what is the target element.
  const headerCellEl = e.currentTarget;

  // If the column is NOT sortable then exit this function
  if (!headerCellEl.querySelector('.sortable')) {
    return;
  }

  // Navigate up from the header cell element to get
  // the '<table>' element.
  let table = headerCellEl.closest('table');

  // Navigate down from the 'table' element to get
  // all of the row elements in the table's body.
  let tableRows = table.querySelectorAll('tbody tr');

  const cellIndex = headerCellEl.cellIndex;

  let order_icon = headerCellEl.querySelector('.sortable');
  let order = encodeURI(order_icon.innerHTML).includes('%E2%86%91') ? 'desc' : 'asc';
  // Update the sort arrow
  order_icon.innerHTML = order === 'desc' ? '&darr;' : '&uarr;';

  let cellList = [];

  tableRows.forEach(rowEl => {
    // Value of each field
    let textContent = rowEl.children[cellIndex].textContent.toUpperCase().trim();

    // stackoverflow.com/questions/31412765/regex-to-remove-white-spaces-blank-lines-and-final-line-break-in-javascript
    const condensedHtml = condenseHTML(rowEl.outerHTML);

    cellList.push({
      textContent: textContent,
      rowHtml: condensedHtml
    });
  });

  const sortedCellList = sortCellList(cellList, order);

  let html = '';

  sortedCellList.forEach(entry => {
    html += entry.rowHtml;
  });

  table.getElementsByTagName('tbody')[0].innerHTML = html;
}

// stackoverflow.com/questions/31412765/regex-to-remove-white-spaces-blank-lines-and-final-line-break-in-javascript
function condenseHTML(html) {
  return html.split('\n')
    .map(s => {
      return s.replace(/^\s*|\s*$/g, "");
    })
    .filter(x => {
      return x;
    })
    .join("");
}

// https://stackoverflow.com/questions/2802341/natural-sort-of-alphanumerical-strings-in-javascript
// "If you have an array of objects, you can do it like this: "
// Answer: https://stackoverflow.com/a/52728388
function sortCellList(cellList, order) {
  if (order === 'desc') {
    return cellList.sort(function(a, b) {
      return a.textContent.localeCompare(b.textContent, undefined, {
        numeric: true,
        sensitivity: 'base'
      });
    });
  }

  return cellList.sort(function(a, b) {
    return b.textContent.localeCompare(a.textContent, undefined, {
      numeric: true,
      sensitivity: 'base'
    });
  });
}
<table border = "1" id = "myTable2" class = "resize-table-font">
  <thead>
    <tr>
      <th>
        <p align = "center">name <span class = "sortable">&uarr;</span></p>
      </th>
      <th>
        <p align = "center">ref <span class = "sortable">&uarr;</span></p>
      </th>
    </tr>
  </thead>
  <tr>
    <td>

      1
    </td>
    <td>
      (book 3: 16)
    </td>

  </tr>
  <tr>
    <td>
      22
    </td>
    <td>
      (book 3: 16)
    </td>


  </tr>
  <tr>
    <td>

      book
    </td>

    <td>
      (book 2: 1-3)
    </td>
  </tr>
  <tr>
    <td>
      2
    </td>

    <td>
      (book 19: 12)
    </td>
  </tr>
  <tr>
    <td>
      how
    </td>
    <td>
      (book 19: 10, 12)
    </td>

  </tr>
  <tr>
    <td>
      when
    </td>
    <td>
      (book 19: 28; 21: 31)؟
    </td>

  </tr>
  <tr>
    <td>
      love
    </td>
    <td>
      (book 19: 30; 21: 31)؟
    </td>

  </tr>
  <tr>
    <td>
      3
    </td>
    <td>
      (book 10: 41; 14: 6, 7; 15: 3)
    </td>

  </tr>
  <tr>
    <td>
      tg
    </td>
    <td>
      (book 21: 30)
    </td>

  </tr>
  <tr>
    <td>

      web
    </td>
    <td>
      (book 19: 26; 21: 30)
    </td>

  </tr>
  <tr>
    <td>
      internet
    </td>
    <td>
      (book 15: 32; 19: 7)
    </td>

  </tr>
  <tr>
    <td>
      far4
    </td>
    <td>
      (book 19: 13)
    </td>

  </tr>
  <tr>
    <td>
      far3
    </td>
    <td>
      (book 21: 32)
    </td>


  </tr>
  <tr>
    <td>
      far33
    </td>
    <td>
      (book 20: 8; 21: 27)
    </td>

  </tr>
</table>

Локально что-то обнаружил, что иногда при сортировке убирает пробелы помимо вкладок вложенности. Где в коде можно исправить эту проблему? (Я отредактировал исходную таблицу, добавив «ввод» после пробела в строке 16 — после book ).

Mike 03.04.2023 00:23

Я использовал функцию, которая сжимает HTML. Имя функции condenseHTML. Замените вызов этой функции в строке: const condensedHtml = condenseHTML(rowEl.outerHTML); и замените его исходным кодом, извлекающим внешний HTML-код строки: const condensedHtml = rowEl.outerHTML.replace(/(\t)|(\n)/g, '');. Однако метод replace заменяет вкладки (\t) пустой строкой. Удалите использование \t, если вы планируете вести вкладки.

Dave B 03.04.2023 01:17

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