/** * delcare a table as sortable by adding class 'js-sortable' */ (function() { 'use strict'; window.utils = window.utils || {}; window.utils.sortable = function(table) { var ASC = 1; var DESC = -1; var trs, ths, sortBy, sortDir, trContents; function setup() { trs = table.querySelectorAll('tr'); ths = table.querySelectorAll('th'); sortBy = 0; sortDir = ASC; 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(thIndex); }); }); } else { // register table rows trContents.push(Array.from(tr.querySelectorAll('td')).map(function(td) { return td.innerHTML; })); } }); } setup(); function updateThs(thIndex, sortOrder) { Array.from(ths).forEach(function (th) { th.classList.remove('sorted-asc', 'sorted-desc'); }); var suffix = sortOrder > 0 ? 'asc' : 'desc'; ths[thIndex].classList.add('sorted-' + suffix); } function sortTableBy(thIndex) { var sortKey = thIndex; var sortOrder = ASC; if (sortBy === sortKey) { sortOrder = sortDir === ASC ? DESC : ASC; } trContents.sort(dynamicSortByType(sortKey, sortOrder)); trContents.sort(dynamicSortByKey(sortKey, sortOrder)); sortBy = thIndex; sortDir = sortOrder; updateThs(thIndex, sortOrder); Array.from(trs).forEach(function(tr, trIndex) { if (trIndex > 0) { Array.from(tr.querySelectorAll('td')).forEach(function (td, tdIndex) { td.innerHTML = trContents[trIndex - 1][tdIndex]; }); } }); } function dynamicSortByKey(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))) { return 1; } aVal = isNaN(aVal) ? a[key] : aVal; bVal = isNaN(bVal) ? b[key] : bVal; var result = (aVal < bVal) ? -1 : (aVal > bVal) ? 1 : 0; return result * order; } } function dynamicSortByType(key, order) { return function (a,b) { var aVal = parseInt(a[key]); var bVal = parseInt(b[key]); aVal = isNaN(aVal) ? a[key] : aVal; bVal = isNaN(bVal) ? b[key] : bVal; var res = (aVal < bVal ? -1 : aVal > bVal ? 1 : 0); if (isNaN(aVal) && !isNaN(bVal)) { res = -1; } if (!isNaN(aVal) && isNaN(bVal)) { res = 1; } return res * order; } } }; })(); document.addEventListener('DOMContentLoaded', function() { Array.from(document.querySelectorAll('.js-sortable')).forEach(function(table) { utils.sortable(table); }); });