Скрипт для сортировки значений в таблице HTML

Сделать таблицу сортируемой при клике по заголовку колонки легко, просто добавьте атрибут data-sort="sort_table" в тег table, а так же добавьте готовый скрипт.

JavaScript

  Как реализовать сортировку данных в HTML-таблице на сайте.

  Задача: сделать так, чтобы в таблице при клике по ячейке таблицы с названием колонки, происходила сортировка данных по возрастанию и убыванию.

  Вполне решаемая задача, для реализации которой нам понадобится JavaScript.

 


Сортировка в таблице

Демо сортировки таблицы:

  Покликайте по заголовкам колонок:

id Имя Страна Баланс
1 Владимир Россия 147
2 Александр Белорусь 0
3 Lisa Англия 65
4 Мутумба Зимбабве -43
5 Donald США 350
6 Angela Германия 350.2

 

Код HTML

<table class="table_sort">
    <thead>
        <tr>
            <th>id</th>
            <th>Имя</th>
            <th>Страна</th>
            <th>Баланс</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>Владимир</td>
            <td>Россия</td>
            <td>147</td>
        </tr>
        <tr>
            <td>2</td>
            <td>Александр</td>
            <td>Белорусь</td>
            <td>0</td>
        </tr>
        <tr>
            <td>3</td>
            <td>Lisa</td>
            <td>Англия</td>
            <td>65</td>
        </tr>
        <tr>
            <td>4</td>
            <td>Мутумба</td>
            <td>Зимбабве</td>
            <td>-43</td>
        </tr>
        <tr>
            <td>5</td>
            <td>Donald</td>
            <td>США</td>
            <td>350</td>
        </tr>
        <tr>
            <td>6</td>
            <td>Angela</td>
            <td>Германия</td>
            <td>37</td>
        </tr>
    </tbody>
</table>

  Обратите внимание, что у таблицы в открывающем теге table стоит class="table_sort". Именно этот класс для js-скрипта является индикатором того, что таблица должна быть сортируемой.

  Таблица имеет структуру по HTML 5. В её структуре обязательно должны быть thead и tbody. Присутствие в структуре таблице tfoot необязательно, но возможно. tfoot не сломает сортировку таблицы.

Javascript

  Скрипт сортирующий таблицу:

document.addEventListener('DOMContentLoaded', () => {

    const getSort = ({ target }) => {
        const order = (target.dataset.order = -(target.dataset.order || -1));
        const index = [...target.parentNode.cells].indexOf(target);
        const collator = new Intl.Collator(['en', 'ru'], { numeric: true });
        const comparator = (index, order) => (a, b) => order * collator.compare(
            a.children[index].innerHTML,
            b.children[index].innerHTML
        );
        
        for(const tBody of target.closest('table').tBodies)
            tBody.append(...[...tBody.rows].sort(comparator(index, order)));

        for(const cell of target.parentNode.cells)
            cell.classList.toggle('sorted', cell === target);
    };
    
    document.querySelectorAll('.table_sort thead').forEach(tableTH => tableTH.addEventListener('click', () => getSort(event)));
    
});

  Данный скрипт позволяет иметь на странице не одну, а неограниченное количество сортируемых таблиц. Текстовые значения сортируются по алфавитному порядку, а числовые значения по велечине.

  Повторю, что скрипт находит только те таблицы, у которых стоит class="table_sort".

  Если данный скрит вставляете в HTML, через виджеты или модули, то не забудьте его обернуть тегами script

<script>тут код скрипта</script>

 

Стили CSS

  Так же выкладываю стили, которые я написал для демо-таблицы. Их можно взять за основу и подправить или дополнить под ваши нужды:

.table_sort table {
    border-collapse: collapse;
}

.table_sort th {
    color: #ffebcd;
    background: #008b8b;
    cursor: pointer;
}

.table_sort td,
.table_sort th {
    width: 150px;
    height: 40px;
    text-align: center;
    border: 2px solid #846868;
}

.table_sort tbody tr:nth-child(even) {
    background: #e3e3e3;
}

th.sorted[data-order="1"],
th.sorted[data-order="-1"] {
    position: relative;
}

th.sorted[data-order="1"]::after,
th.sorted[data-order="-1"]::after {
    right: 8px;
    position: absolute;
}

th.sorted[data-order="-1"]::after {
	content: "▼"
}

th.sorted[data-order="1"]::after {
	content: "▲"
}

 

Записи по теме
Иконочный шрифт в Joomla 3
иконки Иконочный шрифт Icomoon, который используется в Joomla 3. Таблица иконок с названиями их классов и примеры использования иконок в HTML.

 

 

Комментарии 16
15:15 27.10.2019 #

Большое спасибо за отличный способ! Я заметила, что если в ячейке заголовка столбца - две строки, то треугольник (наверх или вниз) выравнивается по вертикали относительно нижней строки, а очень хотелось бы, чтобы выравнивание по вертикали было по центру ячейки. Подскажите, пожалуйста, как реализовать выравнивание треугольника по центру ячейки (по вертикали).

Спасибо!

15:32 27.10.2019 #

В моём примере у этого треугольничка абсолютное позиционирование. Собственно, его двигать можно при помощи следующих css-свойств: top, right, bottom и left.

Вот к этому фрагменту css:

th.sorted[data-order="1"]::after,th.sorted[data-order="-1"]::after {
    right: 8px;
    position: absolute;
}

допишите свойство top и подберите значение в пикселях. Получится примерно так:

th.sorted[data-order="1"]::after,th.sorted[data-order="-1"]::after {
    top: 15px;
    right: 8px;
    position: absolute;
}
17:43 27.10.2019 #

Большое спасибо!

К сожалению, если в нескольких разных таблицах в строке thead - разное количество текстовых строчек (например, в первой таблице заголовки столбцов состоят из одного слова; а во второй таблице в заголовках столбцов много слов, поэтому получается 2-3 строки), то настройки, подходящие для невысоких строк (напр., top: 1px;) не будут подходить для более высоких строк (там, например, нужно было бы: top: 15px;).

Подскажите, пожалуйста, может быть, есть универсальный способ, чтобы вертикальное положение треугольничка было одинаковым, несмотря на то, сколько текстовых строчек в строке заголовка? Спасибо!

22:37 27.10.2019 #

Подскажите, пожалуйста, может быть, есть универсальный способ, чтобы вертикальное положение треугольничка было одинаковым, несмотря на то, сколько текстовых строчек в строке заголовка?

Чтобы в такой ситуации отцентрировать, можно top в процентах указать, высчитывая откат на смещение через calc:

top: calc(50% - 8px);

где 8px - это значение половины высоты шрифта, то есть значение font-size делим на 2. Если у меня размер шрифта 16px - получается в calc берём 8px.

Или более универсально, чтобы от размера шрифта не зависеть, можно сделать так:

top: 50%;
transform: translate(0, -50%);
11:17 28.10.2019 #

Или более универсально, чтобы от размера шрифта не зависеть, можно сделать так:

top: 50%;
transform: translate(0, -50%);

Большое спасибо! Попробовала этот способ, всё отлично работает!

13:54 23.12.2019 #

Sos скрипт не работает в мазилле. Что делать?

14:11 23.12.2019 #

Я в мазиле вот открыл и у меня демка на этой странице работает. Может у вас мазила давно не обновлялась? Типа стоит версия браузера которая не поддерживает ES6.

Можно попробовать скрипт через бабель прогнать чтобы в старых браузерах работало.

Попробуйте так:

"use strict";

function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }

function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }

function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }

document.addEventListener('DOMContentLoaded', function () {
  var getSort = function getSort(_ref) {
    var target = _ref.target;
    var order = target.dataset.order = -(target.dataset.order || -1);

    var index = _toConsumableArray(target.parentNode.cells).indexOf(target);

    var collator = new Intl.Collator(['en', 'ru'], {
      numeric: true
    });

    var comparator = function comparator(index, order) {
      return function (a, b) {
        return order * collator.compare(a.children[index].innerHTML, b.children[index].innerHTML);
      };
    };

    var _iteratorNormalCompletion = true;
    var _didIteratorError = false;
    var _iteratorError = undefined;

    try {
      for (var _iterator = target.closest('table').tBodies[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
        var tBody = _step.value;
        tBody.append.apply(tBody, _toConsumableArray(_toConsumableArray(tBody.rows).sort(comparator(index, order))));
      }
    } catch (err) {
      _didIteratorError = true;
      _iteratorError = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion && _iterator.return != null) {
          _iterator.return();
        }
      } finally {
        if (_didIteratorError) {
          throw _iteratorError;
        }
      }
    }

    var _iteratorNormalCompletion2 = true;
    var _didIteratorError2 = false;
    var _iteratorError2 = undefined;

    try {
      for (var _iterator2 = target.parentNode.cells[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
        var cell = _step2.value;
        cell.classList.toggle('sorted', cell === target);
      }
    } catch (err) {
      _didIteratorError2 = true;
      _iteratorError2 = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
          _iterator2.return();
        }
      } finally {
        if (_didIteratorError2) {
          throw _iteratorError2;
        }
      }
    }
  };

  document.querySelectorAll('.table_sort thead').forEach(function (tableTH) {
    return tableTH.addEventListener('click', function () {
      return getSort(event);
    });
  });
});

Я это в онлайновом инструменте на сайте бабеля перекомпилировал. На работоспособность не проверял. Если сработает, то могу скрипт у себя локально в гальпе прогнать через бабель и минификатор, чтобы по весу не растягивать скрипт.

20:52 25.12.2019 #

Здравствуйте, спасибо вам за интересный, нативный способ сортировки для таблиц.  Единственное о чем хотелось бы вас попросить оставляйте пожалуйста комментарии для кода. Попытался самостоятельно разобраться, все вроде понял, но сам бы на вряд ли додумался) Возможно, тем кто захочет разобраться будет полезно. https://codepen.io/Sergei_Sergeevu4/pen/OJPgOao?editors=0010

p.s Белорусь -> Беларусь

16:30 29.01.2020 #

Вы нереально круты. Огромное спасибо за классный способ сортировки. С уважением и признательностью, Андрей К.

22:01 11.02.2020 #

Отличный скрипт! А как можно сделать, чтобы по-умолчанию сортировало в обратном порядке?

22:03 11.02.2020 #

Сортировку по умолчанию задаёте вы когда заполняете таблицу.

23:04 11.02.2020 #

Я имею в виду при клике чтобы от Я до А была сортировка. А то два клика делать неудобно каждый раз.

23:25 11.02.2020 #

Я понял. Может вам нужен скрипт попроще чтобы только по одной колонке сортировал?

А в данном скрипте с логикой всё правильно. Он сортирует по любой из колонок таблицы по алфавиту и по числам. В начале по порядку, потом в обратном порядке.

Возможно у вас какой то индувидуальный случай, где нужно сортировать по числам от большего к меньшему и не по всем колонкам а по каким то отдельным. Тогда вам нужно писать уникальный скрипт.

А у меня в данном случае универсальный скрипт для общего применения.

23:44 11.02.2020 #

Спасибо за быстрый ответ. Попробую поискать подобный скрипт.

09:08 18.02.2020 #

Добрый день,как можно добавить сохранение состояние сортировки (убывание,увеличение) между страниц при пагинации?

09:23 18.02.2020 #

Я так понимаю это список записей выводится в табличном виде.

При помощи js можно записывать данные в память браузера. Свойство называется localStorage. Но тут плохо тем что будет перерисовка (сортировка) после загрузки дома страницы.

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


*** чтобы писать комментарии.