Откуда появляются новые задачи для Сортировщика таблиц? От пользователей (например, добавить фильтрацию данных) и от самого материала: если его объём велик, быстрая сортировка и поиск невозможны без постраничного вывода (paginate)

Сортировщик HTML таблиц, версия 1

В предыдущей статье мы попытались определить минимально необходимые свойства сортировщика таблиц. Вряд ли произведённые определения можно сильно оспорить; другие минималистские сортировщики в общем с ними согласуются.

Максимальный список задач для сортировщика HTML-таблиц тоже определить несложно – напихать туда всё, что только можно собрать (включая массовое переименование файлов, растеризацию postscript и отправку почты), и дело с концом.

Самое сложное – найти золотую середину. Или хотя бы только один, первый шаг в сторону усложнения Simple Table Sorter. Сейчас наш маленький сортировщик – абсолютно законченная, совершенная вещь в себе; любой сдвиг может нарушить равновесие и всё испортить. Попробуем понять, чего же «нулевой» версии не хватает.

Два источника новых задач: пользователи и материал

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

(1) Требование со стороны материала (HTML-таблиц), в общем, только одно: возможность обрабатывать большие объёмы.

Требования со стороны пользователей тоже неоднородны по весу. Их условно можно разделить на «рюшечки для души» и на «системные». Последние, конечно, важнее. Одно из них прямо вытекает из логики программы. Для чего вообще сортировать таблицы? – Чтобы представить данные в более удобном виде. А для чего этот более удобный вид? – Чтобы быстрее что-то в таблице найти. Сортировка – это, в сущности, косвенный способ отбора, поиска данных.

(2) Таким образом, первое системное улучшение «от пользователей» – добавление прямого поиска – фильтрации, отбора данных по столбцам таблицы.

Вот, собственно, и всё. Если попытаться выполнить хотя бы одно требование материала (1) и одно требование пользователей (2), Simple Table Sorter неизбежно и немедленно превратится в Big Table Sorter; то есть для Простого сортировщика возможна только одна версия. Теоретически можно, конечно, попытаться добавить фильтрацию данных без учёта больших объёмов текста, но это просто будет лишняя работа, так сильно всё в программе взаимосвязано. То есть поиск данных для таблицы в 200 строк будет радикально отличаться от поиска для таблицы в 2000 строк, а с учётом того что массив для поиска и сортировки используется один (для скорости работы и внутренней логичности программы), переделывать пришлось бы всю программу.

Алгоритмы поиска и сортировки для больших объёмов

Принципы работы с большими таблицами в браузере подробно описаны в статье Javascript база данных.

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

В итоге схема программы вырисовывается примерно такая:

  1. Отключаем отображение TBODY сортируемых таблиц (можно прямо правилом CSS .sortable {display:none;} – в файле tabsort1.css).
  2. При открытии страницы удаляем TBODY (для всех таблиц class='sortable', дальше всегда подразумевается это), присоединяя его к вновь созданному элементу TABLE (вне DOM).
  3. Н-да. Предъявляем пользователям строгие требования: TBODY и THEAD должны быть обозначены в таблице явно.
  4. Из удалённого TBODY создаём массив rarr (=rows array) для сортировки и поиска данных. Массив «всеобщий» – сразу для всех (соответствующих требованиям программы) столбцов таблицы. Используем «строгий» подход: в массив попадают только столбцы с явно заданным типом сортировки (axis='num', axis='datru'...), а не наоборот, как в аналогах (исключаются столбцы с class='nosort').
  5. Массив хранится в виде свойства для каждой таблицы.
  6. Выводим на экран первую страницу таблицы (по умолчанию 20 строк, можно менять): 1) из массива формируем TBODY нужного размера; 2) меняем класснэйм таблицы на sortable_vis; 3) присоединяем сформированный TBODY к таблице.
  7. Над таблицей рисуем панель управления страницами.
  8. В каждой ячейке заголовка (с явно указанным типом сортировки) рисуем поле ввода для фильтрации данных.
  9. В случае (успешного) действия «фильтрация» со стороны пользователя, создаём новый массив vrarr (=visual rows array), дальнейшая фильтрация или сортировка ведутся по этому новому массиву – что сильно ускоряет работу.
  10. В случае любых действий пользователя по сортировке (или успешных по поиску или листанию страниц) формируем новый TBODY (размером в одну страницу) и присоединяем к таблице вместо старого.

Структура кода

Ядро Простого сортировщика находится у нас внутри одного объекта (функции) и состоит из двух основных функций: подготовки таблиц и обработки действий пользователя. Мы бы хотели сохранить это и дальше, в Большом сортировщике. Но код в нём вырастет лавинообразно. Я бы даже сказал, взрывообразно. И для удобства работы с этим кодом лучше вынести вспомогательные функции в отдельный файл.

Хотя бы один отдельный файл – потому что по своему назначению вспомогательные элементы можно разделить минимум на три группы: 1) обслуживающие функции «общего назначения» типа trim(), getCookie(); 2) рисование HTML-элементов (типа полей ввода для поиска); 3) обработка подключаемых модулей (типа «Сохранять состояние сортировки между загрузками», «Вести хронометраж»).

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

Дистрибутив и использование

Готовый набор с учётом предлагаемого минимума функциональности находится в файле BigTableSorter1.zip.

Подключать, как предыдущий, но вписывать в HEAD HTML-страницы надо больше файлов:

А к оформлению таблицы предъявляются более строгие требования:

1) Обязательно наличие элемента THEAD, внутри которого должна находится одна строка с ячейками заголовка таблицы.

2) В ячейках заголовка обязательно указывать явно тип данных для сортировки, с помощью атрибута axis:

Если не указать тип данных явно (в виде axis='num' или axis='str'), колонка сортироваться не будет.

3) TBODY можно в таблице явно не указывать; но если указывать, то этот элемент должен быть в таблице только один.

Чтобы отключить вывод хронометража, нужно в 3-ей строке файла tabtools1.js указать show_log: false. Измерение скорости установлено по умолчанию, так как это тестовая версия – по сути, «болванка», для которой можно теперь наращивать функциональность, пока не дорастёт до полного Big Table Sorter 3. Да, полная версия уже существует! :-) Но она недостаточно оптимально написана. Поэтому и создаю для неё заново более правильный, аккуратный «скелет».

Настройки

В начале файла tabtools1.js находится объект def, содержащий в первой, минимальной версии следующие данные для настройки:

  1. use_zebra: true Добавляет чётным строкам таблицы бледно-серый оттенок (или зелёный? или нечётным? ну, в общем, это легко отключить, поставив здесь false).
  2. show_log: true Добавляет вверху страницы чёрную полоску с сообщениями о времени для каждой операции: создания начального массива, сортировки, фильтрации...
  3. arrows_draw: true По умолчанию стрелки используются не картинками (gif), а рисованные (на CSS). Не могу лишний раз с удовольствием и благодарностью не упомянуть Илью Лебедева (http://debugger.ru/blog/bystraja_sortirovka_tablic, ilya@lebedev.net), у которого позаимствовал эту логичную идею. Если поставить здесь false, стрелки будут делаться с помощью фоновых изображений (такое бывает нужно, чтоб не мешать буквам заголовка).
  4. paginate:true Эту опцию отключить нельзя :-). Если поставить здесь false, просто исчезнет панель навигации (листания страниц), и размер страницы увеличится до размера сортировочного массива. То есть всегда будет равным ему (сортировочный массив меняется динамически).
  5. use_inputs:true Добавляет к заголовочным ячейкам поля ввода для поиска значений по данной колонке таблицы. Если тип данных указан num, добавляется два поля ввода – чтоб искать диапазон "от" и "до".

Вот и всё. Никаких тебе use_cookie для сохранения состояния сортировки, или is_dict для работы с большим словарём, как в версии 3 (BigTableSorter.zip). Об этом будет следующая статья.

D.M., admin

Комментарии

лесник 22.12.2010 05:36:50

Поправочка. Разрабатывая новый сайт для телефонного справочника «Иркутские Жёлтые Страницы», я заметил, что в Сортировщике кое-чего не хватает. Нужно дополнить список необходимых задач подсвечиванием искомого фрагмента (в отобранных при фильтрации строках таблицы). Мелочь, но очень удобно:

podsvetka.gif

После добавления этой возможности в телефонный справочник, добавил её также и в исходный BigTableSorter1.