Сортировка значений в таблице
Как реализовать сортировку данных в HTML-таблице на сайте.
Задача: сделать так, чтобы в таблице при клике по ячейке таблицы с названием колонки, происходила сортировка данных по возрастанию и убыванию.
Вполне решаемая задача, для реализации которой нам понадобится JavaScript.
Демо с сортировкой в таблице
Покликайте по заголовкам колонок:
id | Имя | Страна | Баланс |
---|---|---|---|
1 | Радж | Индия | 135 |
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>135</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: "▲"
}
Большое спасибо за отличный способ! Я заметила, что если в ячейке заголовка столбца - две строки, то треугольник (наверх или вниз) выравнивается по вертикали относительно нижней строки, а очень хотелось бы, чтобы выравнивание по вертикали было по центру ячейки. Подскажите, пожалуйста, как реализовать выравнивание треугольника по центру ячейки (по вертикали).
Спасибо!
В моём примере у этого треугольничка абсолютное позиционирование. Собственно, его двигать можно при помощи следующих css-свойств: top, right, bottom и left.
Вот к этому фрагменту css:
допишите свойство top и подберите значение в пикселях. Получится примерно так:
Большое спасибо!
К сожалению, если в нескольких разных таблицах в строке
thead
- разное количество текстовых строчек (например, в первой таблице заголовки столбцов состоят из одного слова; а во второй таблице в заголовках столбцов много слов, поэтому получается 2-3 строки), то настройки, подходящие для невысоких строк (напр.,top: 1px;
) не будут подходить для более высоких строк (там, например, нужно было бы:top: 15px;
).Подскажите, пожалуйста, может быть, есть универсальный способ, чтобы вертикальное положение треугольничка было одинаковым, несмотря на то, сколько текстовых строчек в строке заголовка? Спасибо!
Чтобы в такой ситуации отцентрировать, можно top в процентах указать, высчитывая откат на смещение через calc:
где 8px - это значение половины высоты шрифта, то есть значение font-size делим на 2. Если у меня размер шрифта 16px - получается в calc берём 8px.
Или более универсально, чтобы от размера шрифта не зависеть, можно сделать так:
Большое спасибо! Попробовала этот способ, всё отлично работает!
Sos скрипт не работает в Mozilla. Что мне нужно сделать?
Я в мазиле вот открыл и у меня демка на этой странице работает. Может у вас мазила давно не обновлялась? Типа стоит версия браузера которая не поддерживает ES6.
Можно попробовать скрипт через бабель прогнать чтобы в старых браузерах работало.
Попробуйте так:
Я это в онлайновом инструменте на сайте бабеля перекомпилировал. На работоспособность не проверял. Если сработает, то могу скрипт у себя локально в гальпе прогнать через бабель и минификатор, чтобы по весу не растягивать скрипт.
Здравствуйте, спасибо вам за интересный, нативный способ сортировки для таблиц. Единственное о чем хотелось бы вас попросить оставляйте пожалуйста комментарии для кода. Попытался самостоятельно разобраться, все вроде понял, но сам бы на вряд ли додумался)
Вы нереально круты. Огромное спасибо за классный способ сортировки. С уважением и признательностью, Андрей К.
Отличный скрипт! А как можно сделать, чтобы по-умолчанию сортировало в обратном порядке?
Сортировку по умолчанию задаёте вы когда заполняете таблицу.
Я имею в виду при клике чтобы от Я до А была сортировка. А то два клика делать неудобно каждый раз.
Я понял. Может вам нужен скрипт попроще чтобы только по одной колонке сортировал?
А в данном скрипте с логикой всё правильно. Он сортирует по любой из колонок таблицы по алфавиту и по числам. В начале по порядку, потом в обратном порядке.
Возможно у вас какой то индувидуальный случай, где нужно сортировать по числам от большего к меньшему и не по всем колонкам а по каким то отдельным. Тогда вам нужно писать уникальный скрипт.
А у меня в данном случае универсальный скрипт для общего применения.
Спасибо за быстрый ответ. Попробую поискать подобный скрипт.
Добрый день,как можно добавить сохранение состояние сортировки (убывание,увеличение) между страниц при пагинации?
Я так понимаю это список записей выводится в табличном виде.
При помощи js можно записывать данные в память браузера. Свойство называется
localStorage
. Но тут плохо тем что будет перерисовка (сортировка) после загрузки дома страницы.Я может не совсем правильно понял задачу, но по моему тут лучше делать сортировку на сервере, чтобы данные приходили уже в отсортированном виде.
Как быть с данными типа float? Сортирует как текст((( Вернее работает, но если вывести с форматированием, где пробел между тысячами, то не работает. ))) Красотой приходится жертвовать.
float
это вы имеете в виду числа с плавающей точкой?Может у вас запятая проставлена в этих числах, а не точка?
а как отсортировать допустим все кроме первого столбца? первый столбец будет указывать просто номер строки? то есть если мы сортируем по другим значениям, то значения в первом столбце с id не сортируются
Самое простое решение, можно после сортировки взять и переписать индексы первого столбца:
Я из консоли браузера попробовал, вроде всё правильно.
Вставил в скрипт:
Отличный скрипт, все работает. но подскажите пожалуйста, как сделать что бы изначально в первой колонке (в случае с примером - в ячейке "id") отображалась стрелочка вниз, типо что бы пользователю было наглядно, что есть сортировка и изначальна она по первой колонке?)
Чтобы такое сделать, нужно для этой ячейки в шапке таблицы в хтмле прописать
class="sorted"
и дата-атрибутdata-order="-1"
. Должно получиться так:Это в css-стилях прописано.
Если
data-order="-1"
то будет ▼А если
data-order="1"
то ▲Скрипт работает великолепно, спасибо! Единственное, подскажите, пожалуйста, можно ли как-то "выкинуть" последнюю строчку из сортировки? Дело в том, что в ней у меня объединены все ячейки и с таким условием сортировка не работает =(
Так вы в такой ситуации делайте футер таблицы.
Просто эту последнюю строку прописывайте не в
<tbody>
а в<tfoot>
И правда, спасибо огромнейшее!
Здравствуйте! Хочу поблагодарить за скрипт! Часто его использую, он великолепен))
Только возникла проблема в ie11, при получении индекса он вылетает с ошибкой неитерируемый объект.(через babel скрипт прогнал) Думаю ошибка в том что в ie11 для
querySelectorAll
не работаетforEach
и я переписал[].forEach.call()
.Не могу разобраться как пофиксить
Если честно, я даже не знаю как работает IE и никаких полифилов для него никогда не писал.
Я игнорирую браузер IE и само его существование. Что в css, что в js я его просто игнорирую. Считаю что у кого IE или оська Android ниже 4.4 пусть меняют свои устройства. Я использую флексы и svg.
Но тут ещё такой момент, что это всё должен делать бабель. Там как и у автопрефексера можно задать в настройках поддержку браузеров. Вот посмотрите здесь https://babeljs.io/docs/en/babel-preset-env#options есть такой пример:
Оказалось у ie11 HTMLCollection не имеют метода перебора, поэтому
for in
не работал, переписал под тот же самыйforEach
)Респект автору! Один из самых не капризных и простых скриптов! Удачи в жизни, в самоизоляции и без неё!
Спасибо за скрипт - работает на все 100%.
Единственно, мне необходимо, чтобы по клику сортировка была всегда только в одном порядке - в порядке убывания. Подскажите, как это можно сделать?
Чтобы по-умолчанию при первом клике сортировка была в порядке убывания я поменял значение с -1 на 1
Но как сделать так, чтобы при повторном клике не сортировалось в обратном порядке - не знаю.
А есть пример таблицы в html-формате? Пусть данные будут фейковые, просто чтобы понять какая таблица.
Там может у вас на числовых данных и можно работу скрипта упростить. Ну и мне не верстать для тестирования.
Да, конечно и спасибо за оперативный отклик!!!
а в html есть? На пять строк для тестирования.
И по каким столбцам нужно сортировать?
Сортировка только в одну сторону (от большего к меньшему) нужна по столбцам рейтинг1, рейтинг2, рейтинг3
В общем, столбцам по которым сортировка нужна добавил класс
col_sort
. Получается так:Скрипт:
Вроде всё как вам нужно. Добавил чтобы первый столбец индексы с единицы начинались после сортировки. Если таблица будет с пагинацией то на это стоит обратить внимание. Хотя тут пагинацию делать не получится, не логично. Пагинацию можно сделать только по отдельному рейтингу, а не в сводной таблице. Я понял что первая фамилия - Магнус, ну и где то там есть бурят Накамура.
Я весь css повторять не буду, просто покажу что курсор где комментарий нужно убрать и добавить его отдельно для колонок в которых есть сортировка:
Там в css можно ещё лишних стилей убрать и немного подчистить, если вы взяли стили с моего примера.
Так же могу порекомендовать сделать липкую шапку таблицы: https://precode.top/b/p/sticky-thead Там вообще один стиль нужно добавить.
Просто 5+! Огромное при огромное спасибо за помощь!!!
P.S. Если на странице более чем одна такая таблица, то у всех таблиц после клика первый столбец перезаписывается и нумерация начинает идти подряд (т.е. у второй таблицы первый номер меняется на +1 от последнего номера в первой таблице). Решил прописыванием отдельно скрипта для каждой таблицы.
Здравствуйте, хотелось бы вас поблагодарить за вашу работу. Так же есть небольшая просьба: добавить комментарии к коду, т.к., честно говоря, некоторые вещи в вашем коде мне не понятны. Так же хотелось бы заметить, что скрипт не совсем корректно сортирует отрицательные значения: то есть если у нас будет выборка 1,2 -3 0,7 -,03, то ваш скрипт отсортирует их 1,2 0,7 -3 -0,3, хотя -0,3 больше чем -3. Я по-этому и попросил добавить комментарии, т.к. не смог разобраться, как это пофиксить. Спасибо!
А если в качестве разделителя десятичных знаков ставить точку а не запятую, тоже будет неправильно сортировать данный пример?
Доброе утро, да, только что потестил
Можете пожалуйста доработать сортировку отрицательных чисел?
Спасибо автору за скрипт!!!
Сразу скажу - я не программист.
Для себя заменил .innerHTML на .textContent (comparator ), т.к. использую вложенные теги цвета и по отображаемому тексту сортируется, соответственно, не правильно.
На счет отрицательных чисел и вообще чисел, я добавил условие "если число", то использовать другую функцию сортировки:
Да, согласен. Посмотрел, есть ошибка в сортировке с отрицательными числами.
Исправить текущий скрипт не могу. Тут нужно с нуля заново всё писать, а у меня на данный момент в этом нет нужды.
Извиняюсь, но мне сидеть над этим сейчас некогда.
Скрипт очень понравился, работает без обновления страницы. Но под мой пример не подходит, так как использую две таблицы для организации прокрутки - первая таблица в виде шапки зафиксирована, вторая прокручивается (class-2). Понимаю, что нужно что-то поменять в скрипте, но в нем совсем не разбираюсь.
*** Войдите чтобы писать комментарии.