Tables: initial ФИО order, click-to-sort columns, substring search
- identity group detail (and thus every student list) is ordered by full name; defense rows on the group page sorted by name + lab number - tablekit.js: click a header to sort (numeric-aware, ru locale), second click flips direction (▲/▼ indicator); search input with data-target filters rows by substring live - tables wired: group matrix (with data-sort on variant cells), defense table (data-sort on status/date), students table, lab assignment lists per group, groups list and labs list; name/number columns pre-marked ascending - non-sortable columns marked data-nosort (checkbox/actions)
This commit is contained in:
80
web/src/main/resources/static/js/tablekit.js
Normal file
80
web/src/main/resources/static/js/tablekit.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/* tablekit: сортировка по клику на заголовок + живой поиск по строке.
|
||||
Таблицу размечают: <table class="tablekit" id="...">, поле поиска
|
||||
<input class="table-search" data-target="id-таблицы">.
|
||||
Начальная сортировка (ФИО) выполняется на сервере; клик по заголовку меняет её. */
|
||||
(function () {
|
||||
function normalize(value) {
|
||||
return (value || '').trim().toLowerCase().replace(/\s+/g, ' ');
|
||||
}
|
||||
|
||||
function cellValue(cell) {
|
||||
if (!cell) return '';
|
||||
if (cell.dataset && cell.dataset.sort !== undefined) return normalize(cell.dataset.sort);
|
||||
return normalize(cell.textContent);
|
||||
}
|
||||
|
||||
function compared(a, b) {
|
||||
var na = a.match(/-?\d+([.,]\d+)?/g);
|
||||
var nb = b.match(/-?\d+([.,]\d+)?/g);
|
||||
var fa = na ? parseFloat(na[0].replace(',', '.')) : NaN;
|
||||
var fb = nb ? parseFloat(nb[0].replace(',', '.')) : NaN;
|
||||
if (!isNaN(fa) && !isNaN(fb) && fa !== fb) return fa - fb;
|
||||
return a.localeCompare(b, 'ru', { numeric: true, sensitivity: 'base' });
|
||||
}
|
||||
|
||||
function clearMarkers(table, exceptColumn) {
|
||||
var cells = table.tHead.rows[table.tHead.rows.length - 1].cells;
|
||||
for (var i = 0; i < cells.length; i++) {
|
||||
if (i === exceptColumn) continue;
|
||||
cells[i].classList.remove('is-asc', 'is-desc');
|
||||
}
|
||||
}
|
||||
|
||||
function sortColumn(table, index, direction) {
|
||||
var body = table.tBodies[0];
|
||||
if (!body) return;
|
||||
var rows = Array.prototype.slice.call(body.rows);
|
||||
rows.sort(function (a, b) {
|
||||
return compared(cellValue(a.cells[index]), cellValue(b.cells[index]));
|
||||
});
|
||||
if (direction < 0) rows.reverse();
|
||||
rows.forEach(function (row) { body.appendChild(row); });
|
||||
}
|
||||
|
||||
function bind(table) {
|
||||
if (table.dataset.tablekitBound) return;
|
||||
table.dataset.tablekitBound = '1';
|
||||
var head = table.tHead;
|
||||
if (!head) return;
|
||||
var cells = head.rows[head.rows.length - 1].cells;
|
||||
Array.prototype.forEach.call(cells, function (th, index) {
|
||||
if (th.hasAttribute('data-nosort')) return;
|
||||
th.classList.add('th-sortable');
|
||||
th.title = th.title || 'Сортировать по этому столбцу';
|
||||
th.addEventListener('click', function (event) {
|
||||
if (event.target.closest('form, button, a, select, input')) return;
|
||||
var asc = !th.classList.contains('is-asc');
|
||||
clearMarkers(table, index);
|
||||
th.classList.add(asc ? 'is-asc' : 'is-desc');
|
||||
sortColumn(table, index, asc ? 1 : -1);
|
||||
th.title = (th.textContent.trim() || 'Столбец') + ' — ' + (asc ? 'по возрастанию' : 'по убыванию');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function bindSearch(input) {
|
||||
var table = document.getElementById(input.dataset.target);
|
||||
if (!table || !table.tBodies[0]) return;
|
||||
input.addEventListener('input', function () {
|
||||
var query = normalize(input.value);
|
||||
Array.prototype.forEach.call(table.tBodies[0].rows, function (row) {
|
||||
row.classList.toggle('row-hidden', !!query && normalize(row.textContent).indexOf(query) < 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
document.querySelectorAll('table.tablekit').forEach(bind);
|
||||
document.querySelectorAll('input.table-search').forEach(bindSearch);
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user