Сортировка таблицы на jquery без плагинов
Встала задача отсортировать таблицу на яваскрипте по любому столбику. Известный всем плагин tablesorter у меня не заработал, и я решил, что быстрее и удобнее будет написать свой скрипт. Вот, что получилось через час:
Скрипт получился из 20 строк, 1 кб (готовый tablesorter весит 13 кб и дольше «усваивается»). Ещё одно отличие: подготовительные операции для сортировки происходят по клику; это имеет смысл, потому что сортировка нужна не всем.
Первым делом нужно присвоить идентификаторы каждой строчке таблицы. Это лучше сделать сразу на сервере при выводе таблицы:
<tr id="z_1" ><td> ... </td></tr>
<tr id="z_2" ><td> ... </td></tr>
...
Теперь идентификатор будет привязан к строке с данными, и если её переставить в другое место, ничего не перепутается.
Сортировка массива
В интернете можно найти решения, где таблица целиком переводится в многомерный массив, а затем этот массив сортируется, после чего формируется и выводится новая таблица на место старой. Однако мне этот способ показался слишком громоздким, ведь достаточно держать в памяти всего два столбика:
1) по которому происходит сортировка,
2) столбик идентификаторов.
Можно обойтись простым массивом (ключ => значение), где ключ отвечает за номер строки. Но лично мне проще использовать двумерный массив, чтобы не запутаться между ключами и значениями.
На примере моей таблицы:
А первые значения массива указывают, в каком порядке будут идти строки отсортированной таблицы.
Кстати, данный метод аналогичен сортировке в MySQL с использованием вре́менных таблиц.
Во временный массив желательно класть подготовленные значения, которые быстро и легко сравнивать. Лишнее (тэги и css) надо отбросить, отформатированные числа перевести в обычные числа (20 000 → 20000), а строки можно превратить в некие эквиваленты. Например, в моём случае единственный текстовый столбик содержит только два слова: свободен и бронь. У них разная длина, а значит, во временный массив можно записать только длину слов — этого хватит для корректного сравнения.
var z=$(this).children("td").eq(i_s).html().split(" ").join(""); //убираем пробелы
if(isFinite(z)) {z=parseInt(z);} else {z=z.length;} //число остаётся числом, а у строк оставляем только длину
В яваскрипте есть готовый алгоритм сортировки, использующий функцию сравнения двух элементов:
function sName(a,b) { //задаём функцию сравнения
if(a[0] < b[0]) {return (-1)*s_vozr;}
else if(a[0] > b[0]) {return s_vozr;}
else {return 0;}
}
multi.sort(sName); //сортируем массив multi, указав функцию sName
Функция sName(a,b) возвращает −1, 0 или 1. Если умножить возвращаемое значение на −1, то это изменит направление сортировки (по возрастанию или по убыванию). Таким образом, при помощи параметра s_vozr можно управлять направлением сортировки (если повторно кликнули по столбцу, параметр s_vozr меняет знак).
Перестановка строк таблицы
Теперь надо как-то удалить старую таблицу и показать новую, отсортированную. Тесты я не проводил (буду благодарен за ссылки в комментариях), но почти уверен, что экономичнее перемещать небольшие кусочки данных (то есть строки), чем парсить заново всю таблицу. Если это и не оптимизировано сейчас, то в будущем перемещение элементов должно занимать меньше времени, чем удаление старых и обработка новых элементов; а в нашем случае речь идёт о вставке довольно большой таблицы.
Как переделать старую таблицу в новую, используя перемещение строк? Пройдёмся в цикле по нашему вре́менному массиву, перемещая нужные строчки таблицы в её конец.
От того, куда перемещать строки — в конец или в начало — очевидно, зависит получаемое направление сортировки. Но эффективнее их сдвигать именно в конец. А если нужно изменить направление сортировки, то лучше пройтись по массиву в обратную сторону (или изначально сформировать обратный массив).
Перемещение строки c нужным id в конец таблицы (jquery):
$("#id_строки").appendTo($("#id_таблицы"));
Если бы мы хотели удалить строку, а затем поставить её в конец таблицы, то код выглядел бы так:
$("#id_строки").detach().appendTo($("#id_таблицы"));
Я не разбираюсь, как jquery использует ресурсы; но скорее всего, лучше перемещать без предварительного удаления.
Смотрите также
Комментарии
должно быть
function sName(a,b) { if(a[1] < b[1]) {return (-1)*s_vozr;} else if(a[1]> b[1]) {return s_vozr;} else {return 0;} }
multi.push([z,$(this).attr("id")]);
z — первое значение — по нему должна идти сортировка, поэтому a[0] сравнивается с b[0]
сделал вывод чисел через number format, и соответственно в таблице они сортируются неправильно. У вас все работает с вашим скриптом, вы как я понял преобразуете обратно в обычное число (сумму, площадь), можно ли показать, выслать исходники. Спасибо
У меня при нажатии кнопки все ячейки столбца преобразуются в некие эквиваленты. Если это числа, то в числа, если это не числа, то в длину строки. Вот эта функция:
if(isFinite(z) {z=parseInt(z);} else {z=z.length;}
Не работает
plunix.ru/w/sortirovka
(обновите)
Дальнейшие комментарии закрыты. По всем вопросам пишите или звоните мне лично, см. раздел Контакты