Сортировка и отбор данных в браузере
Примерно год назад начал работу над скриптом JS, который назвал Simple Table Sorter. Он должен был быть маленьким (200-300 строк), понятным и быстрым. Как я узнал позже, по лаконичности ему оказалось очень далеко до TinyTable Лейгебера (leigeber.com/2009/03/table-sorter/), но скорость он показывал вполне приемлемую, не хуже jquery.tablesorter.js (jSorter).
Мне хотелось добиться от скрипта большего, чем умеет jSorter. Например, изначально заложить возможность сохранения и восстановления состояния отсортированной таблицы или добавить в заголовок поля ввода для фильтрации данных. Пользователи, тестировавшие скрипт, также подстрекали к различным усовершенствованиям. Всё это привело к тому, что скрипт перерос в размере jSorter, и к версии 2.1 пришлось переименовать его в Big Table Sorter. Большой размер получился, главным образом, оттого что я пытался учесть разные варианты решений, и многие решения оставил в двух вариантах – потому что так и не смог решить, что лучше:
И ещё множество более мелких вопросов. Некоторые волевые решения, конечно, всё равно принимать пришлось. Например, оставить такую удобную вещь, как «подсветка» строк при наведении мыши чисто на CSS (:hover), то есть лишить этой удобной вещи пользователей Интернет Эксплорера (IE). Потому что все варианты «псевдо-hover'ов» страшно IE тормозили. Позже обнаружилось, что фатальный тормоз в IE возникал, в частности от использования table-layout: fixed (который вообще-то в нормальных браузерах используется для ускорения загрузки больших таблиц!). Но к этому времени желание патчить скрипт под недобраузер полностью было убито кучей мелких пакостей и недоработок MS – типа невозможности перезаписать innerHTML у таблицы или наличия значения по умолчанию display: block у элемента tr. Результат работы Протестировать работу скрипта можно на следующих примерах:
Тесты на компьютере 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. |
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
(Спасибо за быстрый ответ!) |
Цитата:
Общий алгоритм такой: строки tr помещаем в массив trs, массив сортируем, потом бежим по нему и для каждого элемента просто делаем tbody.appendChild(trs[i]), в результате они выстроятся в нужном порядке. |
Цитата:
И, кстати, насчёт создаваемых заново элементов. Как показывает упомянутый выше TinyTable, если помещать строки в массив, копируя (cloneNode), работа с ДОМ идёт гораздо быстрее. Этот фокус позволяет практически уравнять по скорости ИЕ и ФФ (без него ИЕ в несколько раз медленнее, что на таблице в 1000 строк фатально). |
Цитата:
|
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. он сильно замедляет код и не работает. |
А зачем тут try-catch вообще? Операции сравнения ошибку не бросят.
|
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
}
а это просто шедевр. извините |
Цитата:
|
Цитата:
|
Цитата:
|
function hasClass(obj, c) {
//http://ir2.ru/javascript-if.aspx
if (!c || !obj) return false // можно просто return
var re = new RegExp('(\\s+|^)' + c + '(\\s+|$)', 'ig') // каждый рас создается новый обьект регулярного выражения. а если с=".*" или пуста "" ? имя класса регистрозависимо.
if (typeof obj == "string") obj = {className: obj} // зачем создаете еше один обьект. это дешево конечно но зачем.
return (re.test(obj.className)) ? re : false // зачем возвращать регулярное выражение ?
}
вот еше, найдите сами.
function getCookie(name) {
var value=new RegExp("(^|;)\\s*"+name+"\\s*\\=\\s*([^;]+)($|;)","i").exec(unescape(document.cookie));
return value && value[2];
}
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
re.test(obj.className). Если там всё-таки строка (у obj нету className), условия что ли использовать? Так: if (typeof obj == "string") re.test(obj.className) else re.test(obj)? Ну, вероятно, можно как-нибудь в "новом стиле": re.test(obj && obj.className), но это проверять нужно... Руки дойдут - подумаю. Цитата:
Не знаю, что вам не нравится в getCookie(). Не могу догадаться. Пока они нормально соотносятся с моими же setCookie() и это работает во всех браузерах... |
Цитата:
в getCookie unescape делать нужно для значения а не для всей куки |
Цитата:
|
Цитата:
|
обновление скрипта
Появилась новая версия Сортировщика HTML таблиц - http://ir2.ru/tabsort3.js
Там можно работать "в режиме словаря" (отметить в секции настройки is_dict = true), при этом скрипт будет создавать нечто вроде индексов, позволяющих находить (по целому слову) строку в таблице с очень высокой скоростью. Пример - http://ir2.ru/latrus.htm (Латинско-русский словарь, 14000 слов). Ну, и всякие paginate улучшены. |
Simple Table Sorter
Готова версия 0 скрипта Simple Table Sorter. Пример: http://ir2.ru/SimpleTableSorter.zip (13 KB). В нём всего 57 строк:
(function(){
var a_re = /[cdu]\_\d+\_[cdu]/, a_color = 1
var hc = function (s, c) {return (" " + s + " ").indexOf(" " + c + " ") !== -1},
ac = function (e, c) {var s = e.className; if (!hc(s, c)) e.className += " " + c}
prepTabs = function (t){
var el, th, cs, c, cell, axis, ts = (t && t.className) ? [t] : document.getElementsByTagName("table")
for (var e in ts) {
el = ts[e]
if (!hc(el.className, "sortable")) continue
if (!el.tHead) {
th = document.createElement("thead")
th.appendChild(el.rows[0])
el.appendChild(th)
}
th = el.tHead
ac(th, "c_0_c")
th.title = "Сортировать"
th.onclick = clicktab
el.sorted = NaN
}
}
var clicktab = function (e) {
e = e || window.event
var obj = e.target || e.srcElement
while (!obj.tagName.match(/^(th|td)$/i)) obj = obj.parentNode
var i = obj.cellIndex, t = obj.parentNode
while (!t.tagName.match(/^table$/i)) t = t.parentNode
var cn = obj.className, verse = /d\_\d+\_d/.test(cn),
dir = (verse) ? "u" : "d", new_cls = dir + "_" + a_color + "_" + dir
if (a_color < 8) a_color++
if (a_re.test(cn)) obj.className = cn.replace(a_re, new_cls)
else obj.className = new_cls
var j = 0, tb = t.tBodies[0], rows = tb.rows, l = rows.length, c, v, vi
if (i !== t.sorted) {
t.sarr = []
for (j; j < l; j++) {
c = rows[j].cells[i]
v = (c) ? (c.innerHTML.replace(/\<[^<>]+?\>/g, "")) : ""
vi = Math.round(100 * parseFloat(v)).toString()
if (!isNaN(vi)) while (vi.length < 10) vi = "0" + vi
else vi = v
t.sarr[j] = [vi, rows[j]]
}
}
t.sarr = (verse) ? t.sarr.reverse() : t.sarr.sort()
t.sorted = i
for (j = 0; j < l; j++) tb.appendChild(t.sarr[j][1])
obj.title = "Отсортировано по " + ((verse) ? "убыванию" : "возрастанию")
}
window.onload = prepTabs
})()
|
Цитата:
Цитата:
|
x-yuri,
как-то у тебя цитаты перепутаны :) Зебра мало чем помогает воспринимать таблицу, при этом реализация её зачастую неудобна, особенно, если таблица потом ещё и сортируется. Реально помогает воспринимать таблицу подсвечивание строки под указателем мыши. А зебра... ну строки как путались, так и путаются, только они ещё цветные. Нормально свёрстанная таблица, в которой строки не налезают друг на друга, а столбцы не сливаются, и без зебры будет нормально читаться. Впрочем это всё только моё мнение :) |
Цитата:
Цитата:
|
Цитата:
В печатных изданиях есть палец :) |
| Часовой пояс GMT +3, время: 14:11. |