Blog. Just Blog

Сортировка строк HTML-таблицы на JavaScript

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
Понадобился скрипт для сортировки строчек HTML-таблицы в зависимости от значений столбцов. В этих ваших интернетах есть немало готовых решений, но, как часто случается на моей работе, постановка задачи включает в себя кучу дополнительных условий. Например, в ячейке таблицы может быть не просто текст, а несколько HTML-тегов, сортируемое значение может быть отформатировано особым образом или к нему могут быть дописаны какие-нибудь дополнительные данные, а то и вовсе отображаемое текстовое значение в ячейке соответствует какому-то внутреннему индексу в системе и сортировать надо именно по этому индексу. Короче, отображаемое содержимое ячеек таблицы не влияет на ожидаемый порядок их сортировки.

Разнобой со значениями, влияющими на сортировку, решается добавлением к каждой строке таблицы набора data-атрибутов, введенных в HTML5. Вкратце, чтобы не грузить вас теорией, data-атрибуты позволяют хранить нужную вам дополнительную информацию в стандартных элементах HTML без применения хаков вроде нестандартных атрибутов, лишних DOM-свойств и т.п. Например:
  1. <tr data-price="10" data-ident="4" data-area="32" data-dev="СуперСтрой">
  2.     <td>менее 10 млн.</td>
  3.     <td>без отделки</td>
  4.     <td>32 м<sup>2</sup></td>
  5.     <td>ООО СуперСтрой</td>
  6. </tr>
  7. <tr data-price="50" data-ident="3" data-area="62.7" data-dev="ПИК">
  8.     <td>50.000.000</td>
  9.     <td>черновая</td>
  10.     <td>62.7 м<sup>2</sup></td>
  11.     <td>ГК "ПИК"</td>
  12. </tr>
Как вы видите, содержимое в data-атрибутах отличается от содержимого ячеек, это как раз те значения, по которым должна выполняться сортировка. Если какой-либо атрибут не указан, то такие строчки будут просто перенесены в начало таблицы.

Для того, чтобы скрипт сортировки правильно работал, таблица должна быть оформлена с обязательным разделением на структурные элементы при помощи тегов thead и tbody:
  1. <table>
  2.   <thead>
  3.     <tr>
  4.       <th>Колонка 1</th>
  5.       <th>Колонка 2</th>
  6.     </tr>
  7.   </thead>
  8.  
  9.   <tbody>
  10.     <tr>
  11.       <td>1.1</td>
  12.       <td>1.2</td>
  13.     </tr>
  14.     <tr>
  15.       <td>2.1</td>
  16.       <td>2.2</td>
  17.     </tr>
  18.   </tbody>
  19. </table>
Теперь сам скрипт для сортировки строчек таблицы. В качестве параметров он принимает идентификатор таблицы, в которой надо произвести сортировку, название data-атрибута, по значениям которого будет выполнена сортировка, направление сортировки (0 - по возрастанию, 1 - по убыванию) и тип сортируемых данных, числовые или строковые.
  1. //-----------------------------------------------------------
  2. // Сортировка строк таблицы
  3. //-----------------------------------------------------------
  4. // id - идентификатор таблицы
  5. // data - атрибут, по которому будут сортироваться строки
  6. // dir - направление сортировки
  7. // type - тип данных для нормализации
  8. //-----------------------------------------------------------
  9. function sort_rows(iddatadirtype) {
  10.     var tbl=document.getElementById(id);
  11.     var tbodies=tbl.getElementsByTagName('tbody');
  12.     var tmp_trs=tbodies[0].getElementsByTagName('tr');
  13.  
  14.     var all_trs=new Array();
  15.     var tmp;
  16.  
  17.     // Проверить и выбрать строки для сортировки
  18.     for (var i=0i<tmp_trs.lengthi++) {
  19.         tmp=tmp_trs[i].getAttribute('data-'+data);
  20.         if (tmp) {
  21.             // Нормализованное значение для сортировки
  22.             tmp_trs[i].sort_value=type(tmp);
  23.             all_trs.push(tmp_trs[i]);
  24.         }
  25.     }
  26.  
  27.     // Сортировка массива строк по значениям
  28.     all_trs.sort(function(a,b) {
  29.         if (a.sort_value==b.sort_value) {
  30.             return 0;
  31.         }
  32.         else {
  33.             return (a.sort_value>b.sort_value?1:-1);
  34.         }
  35.     });
  36.  
  37.     // Изменить порядок сортировки
  38.     if (dir) {
  39.         all_trs.reverse();
  40.     }
  41.  
  42.     // Добавить отсортированные строки обратно в таблицу
  43.     var current_row;
  44.     var last_row=null;
  45.     for (i=all_trs.length-1i>0i--) {
  46.         all_trs[i].parentNode.insertBefore(all_trs[i],last_row);
  47.         last_row=all_trs[i];
  48.     }
  49. }
Скрипт получился кроссбраузерный, довольно шустро работает во всех современных мобильных и стационарных браузерах. Старые браузеры могут ругнуться на data-атрибуты, но проблем с функционалом тоже быть не должно.

Еще одно условие задачи: переключатели для выбора варианта сортировки могут находиться за пределами таблицы. Поэтому привязывать действие сортировки на клик по заголовку столбца, как это сделано в большинстве аналогичных скриптов, я не буду. Вместо этого в нужном месте по нужному событию вызывается функция сортировки с необходимыми параметрами. Вот пара примеров вызова:
  1. // Отсортировать по колонке "Цена" по возрастанию числовых значений
  2. sort_rows('tt','price',0,Number);
  3.  
  4. // Отсортировать по колонке "Застройщик" по убыванию строковых значений
  5. sort_rows('tt','dev',1,String);
В тестовом примере эти обработчики добавлены к стрелочкам в заголовки колонок. На реальных проектах они могут быть привязаны к любому другому элементу страницы.

К известным недостаткам скрипта могу отнести невозможность одновременной сортировки по нескольким столбцам, но такой необходимости не возникало. В рабочих проектах все данные известны, все таблицы оформлены нужным образом, а для использования скрипта в "дикой природе" не мешало бы добавить несколько проверок на корректность структуры таблицы и типов входящих данных. И еще было бы хорошо добавить обработку строк с отсутствующими data-атрибутами, например, переносить их в конец таблицы. Повторюсь, в моем случае такой задачи не стояло, это вы можете сделать самостоятельно.

Посмотреть рабочий пример сортировки строк HTML-таблицы вы можете на демонстрационной странице.

Поделиться ссылкой ВКонтакте
Просмотров: 5105 | Комментариев: 7

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (09.03.2020 в 16:54):
Так в чем проблема взять и дописать весь нужный функционал?
izhadapter (09.03.2020 в 10:37):
Спасибо.
Хорошо бы куки еще учитывать чтоб сохранялась сортировка при перезагрузке страницы
ipSlicer (26.01.2019 в 06:13):
Что-то я не увидел #кодсократилсявразы на vie, но вот демонстрационная табличка показательная. Да. Польза от vie только для программиста, а как начнешь спрашивать, что реально можно посмотреть на vie кроме эффектных демонстраций, так сразу начинают мяться и рассуждать о скорости работы с виртуальным DOM. :) Мода на фреймворк пройдет, а javascript останется.
DiPrm (27.12.2018 в 00:19):
Да, вес скрипта увеличился, но логика упростилась, удобнее воспринимается. Но польза от этого только для программиста)
ManHunter (25.12.2018 в 22:34):
DiPrm, ай, лукавишь. "В разы" будет, когда не будет строчки <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.min.js& quot;>
А так к своим разам прибавляй-умножай размер фреймворка.
DiPrm (25.12.2018 в 22:12):
Попробовал реализовать решение на vue js, код сократился в разы: https://codepen.io/earthwalker/pen/jeVbRm
DiPrm (07.12.2018 в 21:05):
Спасибо! Что-то подобное делал для таблицы, в ячейках которой нужно было показать числа с разбивкой, поэтому для сортировки использовал атрибут data для самих ячеек.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.06 сек. / MySQL: 2 (0.0029 сек.) / Память: 4.5 Mb
Наверх