Скрипт сортировки таблицы html

JavaScript: сортировка строк в HTML-таблице

Хоть в этой таблице задано лишь три строки (если не считать строки-заголовка), в задаче предупреждают, что решение должно быть для таблицы с любым количеством строк.

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

и

не прописаны (поэтому я отметил их серебристым цветом). Но по правилам языка HTML они обязательно должны быть (секция tbody в таблице по правилам HTML может быть одна или их может быть несколько), поэтому браузер (у меня — «Microsoft Edge» на базе движка «Chromium») добавляет их сам. В этом можно убедиться, запустив для загруженной HTML-страницы с данной HTML-таблицей инструмент «Elements» из инструментов разработчика (F12).

Выглядеть эта HTML-таблица в браузере может по-разному, в зависимости от стилизации с помощью языка CSS. Например, на отдельной странице обсуждаемой задачи в обсуждаемом учебнике эта HTML-таблица показана почти что без стилизации и выглядит некрасиво, примерно так:

Имя Фамилия Возраст
Джон Смит 10
Пётр Браун 15
Анна Ли 5

А на странице раздела 1.7 «Изменение документа» обсуждаемого учебника, в том месте, где описывается эта же задача, данная HTML-таблица выглядит гораздо лучше, примерно так:

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

 table < width: 100%; border-collapse: collapse; font-size: 13px; font-family: "Segoe UI"; >tr:nth-child(2n) < background: #f9f9f9; >tr < border-bottom: 1px solid #ccc; >td, th < padding: 2px 1em 2px 5px; >th

Тут стоит отметить псевдокласс :nth-child (для меня он был в новинку). В данном описании стилей с помощью этого псевдокласса определяется цвет фона ( #f9f9f9 ) каждой четной строки (тег tr ) тестовой HTML-таблицы. При этом нужно иметь в виду, что нумерация строк начинается с единицы. То есть первой строкой является заголовочная строка нашей HTML-таблицы, она нечетная, поэтому ее фон имеет цвет по умолчанию (в данном случае — белый). Вторая строка — это строка, содержащая значения «Джон», «Смит» и «10», она чётная, поэтому ее фон — серого ( #f9f9f9 ) цвета. И так далее. Тут подробнее:

Читайте также:  Format text in html page

Итак, в заданной HTML-таблице по условиям задачи требуется отсортировать строки (то есть переставить их местами) по столбцу «Имя».

В первую очередь я решил выбрать все строки (HTML-элементы tr ) заданной HTML-таблицы. Рука потянулась к методу querySelectorAll , описанному в подразделе 1.4 «Поиск: getElement*, querySelector*» второй части обсуждаемого учебника. Но тут я вспомнил, что для HTML-таблиц существуют более удобные способы работы с частями этих таблиц. Они были описаны в подразделе 1.3 «Навигация по DOM-элементам» второй части обсуждаемого учебника. Например, получить коллекцию строк HTML-таблицы можно с помощью свойства rows HTML-таблицы. При построении тестовой HTML-таблицы ей был дан идентификатор table , поэтому получить коллекцию строк этой таблицы можно с помощью выражения table.rows .

В учебнике было сказано, что получаемая таким образом коллекция HTML-элементов не является массивом (это псевдомассив). А это значит, что к коллекции HTML-элементов нельзя будет применить методы массивов. А мы, ведь, хотим отсортировать строки HTML-таблицы, следовательно, нам нужно отсортировать полученную коллекцию строк HTML-таблицы. Можно, конечно, самому написать метод сортировки для коллекции. Но зачем, если метод сортировки уже написан, хоть и для массива? Просто преобразуем нашу коллекцию строк HTML-таблицы в массив, а затем используем готовый метод сортировки массива. Пишем код:
1.

let arr = Array.from( table.rows ); // преобразуем коллекцию в массив arr.sort(); // используем готовый метод сортировки массива 

В этом коде используется сортировка массива по умолчанию (для метода сортировки не задан параметр). В этом случае элементы массива приводятся к строке, а затем происходит их сравнение. В нашем случае элементы массива являются объектами, HTML-элементами tr . При преобразовании каждого из этих объектов в строку получится одна и та же строка — «[object HTMLTableRowElement]» . Метод сортировки посчитает все элементы массива равными и сортировки не произойдет. Поэтому нам следует прописать функцию, определяющую порядок сортировки, и передать ее в метод сортировки массива первым параметром. Меняем код:
2.

let arr = Array.from( table.rows ); arr.sort( (a, b) => < let str = a.cells[0].textContent; let str2 = b.cells[0].textContent; return str.localeCompare(str2); >);

Здесь функция, определяющая порядок сортировки, не имеет имени и задана стрелочной функцией. У этой функции два входящих параметра — a и b , это два элемента массива, сравниваемых при сортировке массива, выполняемой методом sort . То есть переменные a и b являются в данном случае HTML-элементами tr .

По условиям задачи для сравнения строк нашей HTML-таблицы следует использовать значения столбца «Имя», а этот столбец состоит из первых ячеек (HTML-элементов td или th ) каждой строки нашей HTML-таблицы. Коллекцию этих ячеек можно получить с помощью свойства cells строки HTML-таблицы, это было описано в уже упомянутом подразделе 1.3 «Навигация по DOM-элементам» второй части обсуждаемого учебника. Первая ячейка каждой строки нашей HTML-таблицы и есть cells[0] , а ее текстовое содержимое — cells[0].textContent . Таким образом в переменных str и str2 мы получаем текстовые строки, каждая из которых представляет свой объект [object HTMLTableRowElement] , эти переменные мы и будем использовать для сравнения с помощью метода localeCompare .

Наш код уже отсортировал строки тестовой HTML-таблицы в массиве. Осталось лишь вставить их из массива обратно в тестовую HTML-таблицу. Сделаем это с помощью уже ставшего привычным (я его применял ранее для решения нескольких задач) метода append . В предыдущих постах я его применял для вставки одного HTML-элемента за раз, но, ведь, им можно вставлять сразу несколько HTML-элементов с помощью оператора расширения (многоточие). Меняем код:
3.

let arr = Array.from( table.rows ); arr.sort( (a, b) => < let str = a.cells[0].textContent; let str2 = b.cells[0].textContent; return str.localeCompare(str2); >); table.append(. arr);

Может возникнуть вопрос: если мы только вставляем новые строки в тестовую HTML-таблицу и не удаляем старые, то всего строк теперь должно стать не четыре, а восемь (каждая исходная строка дублируется)? На самом деле, нет, потому что метод append (как и его коллеги) сначала удаляет HTML-элемент со старого места, а затем вставляет его на новое место. То есть фактически вставляются не новые элементы, а исходные.

Наш код отсортировал строки заданной HTML-таблицы и результат отобразился в браузере. Однако, вместе со всеми отсортировалась и заголовочная строка, которая, по идее, должна остаться на своем месте, вверху HTML-таблицы. Я решил отследить эту строку внутри функции, определяющей порядок сортировки, и сделать так, что она не будет двигаться со своего места. Меняем код:
4.

let arr = Array.from( table.rows ); arr.sort( (a, b) => < if (a.cells[0].tagName == "TH" || b.cells[0].tagName == "TH") return 0; let str = a.cells[0].textContent; let str2 = b.cells[0].textContent; return str.localeCompare(str2); >); table.append(. arr);

Это сработало, теперь заголовочная строка остаётся на своем месте. Однако, авторы задачи в своем решении предложили более изящный способ:
5.

let arr = Array.from( table.rows ); arr = arr.slice(1); arr.sort( (a, b) => < let str = a.cells[0].textContent; let str2 = b.cells[0].textContent; return str.localeCompare(str2); >); table.append(. arr);

Метод slice возвращает новый массив, в данном случае — без первого элемента (который и является заголовочной строкой нашей HTML-таблицы), и полученный массив записывается на место старого, в переменную arr . Таким образом, заголовочная строка вообще не принимает участия в сортировке и не перемещается на новое место (не попадает в руки метода append ).

Теперь, казалось бы, всё в порядке. Но нет. Если просмотреть полученную HTML-страницу с помощью инструмента «Elements» из инструментов разработчика (F12) браузера, то можно увидеть, что метод append вставил HTML-элементы tr не внутрь HTML-элемента tbody (как положено по правилам языка HTML), а после него.

В некоторых случаях такое нарушение может повлиять на внешний вид страницы. Например, в случае кода из варианта 4 нашего скрипта (см. выше) собьется порядок окраски фона строк нашей тестовой HTML-таблицы: серым цветом будет окрашен фон нечетных строк (первой и третьей) вместо указанных в стиле четных (второй и четвертой). Это произойдет из-за того, что HTML-элемент tbody станет соседом HTML-элементов tr и при расчете номеров HTML-элементов в этой группе HTML-элементов он будет считаться первым (так как является первым ребенком общего для группы родителя). Таким образом, нумерация собьется и первая строка таблицы будет теперь считаться второй, вторая строка — третьей и так далее.

Чтобы поместить отсортированные строки нашей HTML-таблицы из массива обратно в HTML-элемент tbody , изменим последнюю строчку нашего кода:
6.

let arr = Array.from( table.rows ); arr = arr.slice(1); arr.sort( (a, b) => < let str = a.cells[0].textContent; let str2 = b.cells[0].textContent; return str.localeCompare(str2); >); table.tBodies[0].append(. arr);

Это финальный вариант скрипта. О свойстве tBodies рассказывалось в том же подразделе 1.3 «Навигация по DOM-элементам» второй части обсуждаемого учебника. Секций tbody , как уже упоминалось, в HTML-таблице может быть несколько. В нашем случае такая секция одна.

Источник

Javascript. Сортировка таблицы

Может для большинства здешних обитателей моя статья покажется слишком скучной и «и так понятно», но думаю новичкам будет в чем-то полезной.
Стояла передо мной как-то задача сделать сортировку таблицы по разным колонкам. Данный брались из базы, каждый раз их вытаскивать — накладно, решил задействовать JavaScript.
Были небольшие трудности из-за использования различной стилистики строк в таблице, а именно был разный цвет фона, в зависимости от данных самой таблицы.
Стилистику нарушать было нельзя. Кого заинтересовало, прошу под кат.

Подсветка фона выбрана так:
1) если время < 2012 год — подсветка красным
2) если расстояние > 9000 — подсветка желтым.
*) остальное чередование белого с серым.

Данные талицы берутся из БД, рисуется php, последняя колонка скрыта, это время в UNIX-формате, по ней сортировать колонку «Время» проще.

var TableSort = function (idTbl, defSortCol, firstRow, classes) < // номер колонки, по которой выполнена текущая сортировка, считаем с 0 var curSortCol = defSortCol; // номер колонки, у которой отрисовать картинку, показывающая направление сортировки, считаем с 0 var curImgCol = defSortCol; // направление сортировки вверх var curSortUp = true; // id таблицы, в которой производим сортировку var curIdTbl = idTbl; // номер строки, с которой идут данные, считаем с 0 var numColTr = (firstRow == null) ? 1 : firstRow; // нужно ли учитывать классы для строк if (classes == null) < var style = false; >else < var style = true; // список классов, которые нужно сохранить var needClasses = classes[0]; // список классов, которые чередуются var listClasses = classes[1]; >var tbl = document.getElementById(curIdTbl); var allImgs = new Array(); // all imgs-arrow allThs = tbl.getElementsByTagName('tr').item(0).getElementsByTagName('th'); for (i=0; i else < allImgs[i] = null; >> var tblData = new Array(); // current data in table // начинаем сортировку по колонке newCol, картинку рисуем у колонки imgCol this.initSort = function (newCol, imgCol) < if (newCol == curSortCol) < // кликнули на отсортированную колонку, меняем сортировку на обратную curSortUp = !curSortUp; >else < // сортируем по новой колонке curSortCol = newCol; curImgCol = (imgCol == null) ? newCol : imgCol; curSortUp = true; >showArrow(); getDataTable(); showSortTable(); if (style) < doStyle(); >>; // show/change arrow function showArrow() < for (i=0; ielse < allImgs[i].src = "./img/down.png"; >> else < allImgs[i].style.visibility = "hidden"; >> > > // get new data from table function getDataTable() < allTrs = tbl.getElementsByTagName('tr'); for (i=numColTr; iif (style) < tblData[i-numColTr][allTrs[i].getElementsByTagName('td').length]=allTrs[i].className; >> tblData.sort(_sort); if (!curSortUp) < tblData.reverse(); >> // rules for sorting function _sort(a1, b1) < var a = a1[curSortCol]; var b = b1[curSortCol]; if (parseFloat(a) && parseFloat(b)) < return parseFloat(a) - parseFloat(b); >else < if (a.toLowerCase() < b.toLowerCase()) < return -1; >else if (a.toLowerCase() > b.toLowerCase()) < return 1; >else < return 0; >> > function showSortTable() < allTrs = tbl.getElementsByTagName('tr'); for (i=numColTr; iif (style) < allTrs[i].className=tblData[i-numColTr][allTrs[i].getElementsByTagName('td').length]; >> > function doStyle() < allTrs = tbl.getElementsByTagName('tr'); for (i=numColTr; iif(needClasses.indexOf(allTrs[i].className) != -1) < continue; >allTrs[i].className = listClasses[(i % listClasses.length)]; > > > 
var infoTblSort = new TableSort("idTbl", 0, 1, [['add', 'edd'],['odd', '']] ); 
onclick="infoTblSort.initSort(4,3);" 

В этом примере передается 2 параметра, первый — по которому будет идти сортировка (в данном случае — это скрытая колонка UNIX-время), вторая — колонка, у которой будет стоять картинка, указывающая направление текста.

На этом все, надеюсь мой опыт будет кому-то полезен. Прошу пощения за несколько сумбурный рассказ, впервые пишу статью.
Спасибо за внимание.

Источник

Оцените статью