Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 26.10.2010, 10:23
Аспирант
Отправить личное сообщение для stopkran Посмотреть профиль Найти все сообщения от stopkran
 
Регистрация: 12.12.2009
Сообщений: 54

Сортировка и отбор данных в браузере
Примерно год назад начал работу над скриптом JS, который назвал Simple Table Sorter. Он должен был быть маленьким (200-300 строк), понятным и быстрым. Как я узнал позже, по лаконичности ему оказалось очень далеко до TinyTable Лейгебера (leigeber.com/2009/03/table-sorter/), но скорость он показывал вполне приемлемую, не хуже jquery.tablesorter.js (jSorter).

Мне хотелось добиться от скрипта большего, чем умеет jSorter. Например, изначально заложить возможность сохранения и восстановления состояния отсортированной таблицы или добавить в заголовок поля ввода для фильтрации данных. Пользователи, тестировавшие скрипт, также подстрекали к различным усовершенствованиям. Всё это привело к тому, что скрипт перерос в размере jSorter, и к версии 2.1 пришлось переименовать его в Big Table Sorter.

Большой размер получился, главным образом, оттого что я пытался учесть разные варианты решений, и многие решения оставил в двух вариантах – потому что так и не смог решить, что лучше:
  1. Использовать при отрисовке таблицы innerHTML или appendChild?
  2. Использовать картинки для стрелок, или рисовать стрелки на CSS (идею позаимствовал из SortTable.1.5.1.zip Ильи Лебедева – debugger.ru/blog/bystraja_sortirovka_tablic)?
  3. Делать ли таблицу полосатой («зебра»)?
  4. Разбивать ли на страницы (paginate)?
  5. Добавлять поля отбора всем заголовочным ячейкам, или только тем, у которых явно назначен тип сортировки?
  6. Давать ли возможность пользователям самим определять тип сортировки (удерживая при щелчке Shift или Control)?
  7. Заставлять ли разработчика явно обозначать элементы thead и tbody?

И ещё множество более мелких вопросов. Некоторые волевые решения, конечно, всё равно принимать пришлось. Например, оставить такую удобную вещь, как «подсветка» строк при наведении мыши чисто на CSS (:hover), то есть лишить этой удобной вещи пользователей Интернет Эксплорера (IE). Потому что все варианты «псевдо-hover'ов» страшно IE тормозили.

Позже обнаружилось, что фатальный тормоз в IE возникал, в частности от использования table-layout: fixed (который вообще-то в нормальных браузерах используется для ускорения загрузки больших таблиц!). Но к этому времени желание патчить скрипт под недобраузер полностью было убито кучей мелких пакостей и недоработок MS – типа невозможности перезаписать innerHTML у таблицы или наличия значения по умолчанию display: block у элемента tr.

Результат работы

Протестировать работу скрипта можно на следующих примерах:
  1. ir2.ru/test-tracker/limit202.htm – таблица в 200 строк, для старых компьютеров.
  2. ir2.ru/test-tracker/limit1003.htm – таблица в 1000 строк.
  3. ir2.ru/test-tracker/tracker2.php.htm – таблица в 500 строк, но из-за объёма текстов (500 KB) гораздо более неудобная для обработки, чем предыдущая.
  4. Для сравнения подключил к последнему большому файлу jSorter (ir2.ru/test-tracker/tracker.php.htm) и TinyTableV3 (ir2.ru/test-tracker/tracker3.php.htm).
  5. ir2.ru/test-tracker/limit3000.htm – таблица в 3000 строк (722 KB).
  6. ir2.ru/latrus.htm – Латинско-русский словарь (~14000 строк, 1МB), работает с более новой версией скрипта ir2.ru/tabsort3a.js.

Тесты на компьютере Pentium 4 (2.53GHz, Windows XP) показали, что при использовании предложенного алгоритма разбивки на страницы (paginate) работа с таблицей в 3000 строк почти не отличается от работы с таблицей в 200 строк – в «обычном браузере» (Гекко, Хром, Сафари), конечно. В особом браузере (IE) время отрисовки таблицы не зависит от реального отображения элементов и растёт пропорционально количеству строк. Ну, Опера 9.50 тоже, кажется, испытывает трудности с «рисованием».

Во всех примерах настройки можно менять, отмечая галочками элементы checkbox в начале страницы (изменения настроек чаще всего требуют перезагрузки страницы). Например, можно убрать галочку с пункта use_appendChild (активного по умолчанию), и тогда таблица будет отрисовываться с помощью замены innerHTML (что, предположительно, должно было уменьшить время отрисовки). Нет настройки, позволяющей использовать documentFragment, потому что использование documentFragment не дало никакой выгоды ни в одном браузере.

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

Весь набор файлов, необходимых для работы Big Table Sorter'а, находится в архиве ir2.ru/BigTableSorter.zip.

P.S. Спасибо roni за подсказку убрать букву "i" из регэкспа при работе с className.

Последний раз редактировалось stopkran, 30.10.2010 в 09:37.
Ответить с цитированием
  #2 (permalink)  
Старый 26.10.2010, 10:40
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Сообщение от stopkran
Использовать при отрисовке таблицы innerHTML или appendChild?
При отрисовке во время сортировки?

Сообщение от stopkran
Делать ли таблицу полосатой («зебра»)?
Не надо.

Сообщение от stopkran
Разбивать ли на страницы (paginate)?
Это кому как надо.

Сообщение от stopkran
Давать ли возможность пользователям самим определять тип сортировки (удерживая при щелчке Shift или Control)?
Никто не будет держать shift или control.
Ответить с цитированием
  #3 (permalink)  
Старый 26.10.2010, 11:23
Аспирант
Отправить личное сообщение для stopkran Посмотреть профиль Найти все сообщения от stopkran
 
Регистрация: 12.12.2009
Сообщений: 54

Сообщение от Kolyaj
При отрисовке во время сортировки?
Нет. При отрисовке после сортировки! :-) Сортировать реальный ДОМ в 1000 строк нереально, сначала всё грузится в массив, там сортируется, потом вываливается обратно на экран.

(Спасибо за быстрый ответ!)
Ответить с цитированием
  #4 (permalink)  
Старый 26.10.2010, 11:51
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Сообщение от stopkran
сначала всё грузится в массив, там сортируется, потом вываливается обратно на экран.
Ну это понятно, что на экране не сортируется. А зачем создавать заново элементы, если они уже созданы?
Общий алгоритм такой: строки tr помещаем в массив trs, массив сортируем, потом бежим по нему и для каждого элемента просто делаем tbody.appendChild(trs[i]), в результате они выстроятся в нужном порядке.
Ответить с цитированием
  #5 (permalink)  
Старый 26.10.2010, 12:46
Аспирант
Отправить личное сообщение для stopkran Посмотреть профиль Найти все сообщения от stopkran
 
Регистрация: 12.12.2009
Сообщений: 54

Сообщение от Kolyaj
и для каждого элемента просто делаем tbody.appendChild(trs[i])
Ну, может, я неграмотно выразился, но именно это я и назвал "отрисовкой". При appendChild ведь структура ДОМ меняется? И её потом надо перерисовывать?

И, кстати, насчёт создаваемых заново элементов. Как показывает упомянутый выше TinyTable, если помещать строки в массив, копируя (cloneNode), работа с ДОМ идёт гораздо быстрее. Этот фокус позволяет практически уравнять по скорости ИЕ и ФФ (без него ИЕ в несколько раз медленнее, что на таблице в 1000 строк фатально).
Ответить с цитированием
  #6 (permalink)  
Старый 29.10.2010, 10:38
Профессор
Отправить личное сообщение для with-love-from-siberia Посмотреть профиль Найти все сообщения от with-love-from-siberia
 
Регистрация: 14.12.2009
Сообщений: 155

Сообщение от stopkran
Заставлять ли разработчика явно обозначать элементы thead и tbody?
Видимо не стоит. Ведь кроме thead, tbody есть и tfoot.
Ответить с цитированием
  #7 (permalink)  
Старый 29.10.2010, 13:52
Аватар для vflash
Профессор
Отправить личное сообщение для vflash Посмотреть профиль Найти все сообщения от vflash
 
Регистрация: 09.07.2007
Сообщений: 304

function cmpRowVerse(a, b) {
 a = a[global.sortcell], b = b[global.sortcell];
 try { 
  return (a <= b) ? (a == b) ? 0 : 1 : -1;
 }
 catch(e){return 0;}
}


тут не стоит использовать try catch. он сильно замедляет код и не работает.
__________________
лучшая rss читалка zzreader.com
Ответить с цитированием
  #8 (permalink)  
Старый 29.10.2010, 13:53
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

А зачем тут try-catch вообще? Операции сравнения ошибку не бросят.
Ответить с цитированием
  #9 (permalink)  
Старый 29.10.2010, 14:03
Аватар для vflash
Профессор
Отправить личное сообщение для vflash Посмотреть профиль Найти все сообщения от vflash
 
Регистрация: 09.07.2007
Сообщений: 304

function hasClass(obj, c) {
 //http://ir2.ru/javascript-if.aspx
 if (!c || !obj) return false
 var re = new RegExp('(\\s+|^)' + c + '(\\s+|$)', 'ig')
 if (typeof obj == "string") obj = {className: obj}
 return (re.test(obj.className)) ? re : false
}

а это просто шедевр. извините
__________________
лучшая rss читалка zzreader.com
Ответить с цитированием
  #10 (permalink)  
Старый 30.10.2010, 09:11
Аспирант
Отправить личное сообщение для stopkran Посмотреть профиль Найти все сообщения от stopkran
 
Регистрация: 12.12.2009
Сообщений: 54

Сообщение от with-love-from-siberia Посмотреть сообщение
Видимо не стоит. Ведь кроме thead, tbody есть и tfoot.
Где логика?:-) Если уж вы используете tfoot, про tbody наверняка не забудете. Сейчас скрипт при отсутствии thead сам создаёт этот элемент из первой строчки таблицы. Вопрос в том, сэкономить ли на этом участке кода...
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вставка данных в textarea из модального окна (для Markitup) Roman Koff jQuery 0 26.08.2010 23:21
База данных. Работает только в IE. Izgoj Javascript под браузер 9 29.10.2009 17:20
Сортировка числовых данных в таблице Vladsss Общие вопросы Javascript 15 01.09.2009 17:02
Синхронный запрос данных по AJAX Shasoft AJAX и COMET 2 03.03.2009 14:07
Хранимая область данных. PolarWolf Общие вопросы Javascript 17 14.01.2009 18:25