/** * delcare a table as sortable by adding class 'js-sortable' */ document.addEventListener('DOMContentLoaded', function() { var tables = []; var ASC = 1; var DESC = -1; function initTable(table, tableIndex) { var trs = table.querySelectorAll('tr'); var ths = table.querySelectorAll('th'); var trContents = []; Array.from(trs).forEach(function(tr, rowIndex) { if (rowIndex === 0) { // register table headers as sort-listener Array.from(tr.querySelectorAll('th')).forEach(function(th, thIndex) { th.addEventListener('click', function(el) { sortTableBy(tableIndex, thIndex); }); }); } else { // register table rows trContents.push(Array.from(tr.querySelectorAll('td')).map(function(td) { return td.innerHTML; })); } }); tables.push({ el: table, ths: ths, sortBy: 0, sortDir: ASC, trContents, }); } function updateThs(tableIndex, thIndex, sortOrder) { Array.from(tables[tableIndex].ths).forEach(function (th) { th.classList.remove('sorted-asc', 'sorted-desc'); }); var suffix = sortOrder > 0 ? 'asc' : 'desc'; tables[tableIndex].ths[thIndex].classList.add('sorted-' + suffix); } function sortTableBy(tableIndex, thIndex) { var table = tables[tableIndex]; var sortKey = thIndex; var sortOrder = ASC; if (table.sortBy === sortKey) { sortOrder = table.sortDir === ASC ? DESC : ASC; } table.trContents.sort(dynamicSort(sortKey, sortOrder)); tables[tableIndex].sortBy = thIndex; tables[tableIndex].sortDir = sortOrder; updateThs(tableIndex, thIndex, sortOrder); Array.from(table.el.querySelectorAll('tr')).forEach(function(tr, trIndex) { if (trIndex > 0) { Array.from(tr.querySelectorAll('td')).forEach(function (td, tdIndex) { td.innerHTML = table.trContents[trIndex - 1][tdIndex]; }); } }); } function dynamicSort(key, order) { return function (a,b) { var aVal = parseInt(a[key]); var bVal = parseInt(b[key]); if ((isNaN(aVal) && !isNaN(bVal)) || (!isNaN(aVal) && isNaN(bVal))) { console.error('trying to sort table by row with mixed content: "%s", "%s"', a[key], b[key]); } aVal = isNaN(aVal) ? a[key] : aVal; bVal = isNaN(bVal) ? b[key] : bVal; var result = (aVal < bVal) ? -1 : (aVal > bVal) ? 1 : 0; return result * order; } } var rawTables = document.querySelectorAll('.js-sortable'); Array.from(rawTables).forEach(function(table, i) { initTable(table, i); }); });