From 9a82b9c38538ef34a6fe640b26f6cfd171aaa1e0 Mon Sep 17 00:00:00 2001 From: Felix Hamann Date: Sat, 31 Mar 2018 00:53:03 +0200 Subject: [PATCH] refactor of sortable tables --- templates/home.hamlet | 7 +- templates/standalone/sortable.julius | 183 +++++++++++++++------------ 2 files changed, 107 insertions(+), 83 deletions(-) diff --git a/templates/home.hamlet b/templates/home.hamlet index cd45490d2..36ea5a429 100644 --- a/templates/home.hamlet +++ b/templates/home.hamlet @@ -39,7 +39,7 @@ 0 - 14 + NT2 CON2 3 @@ -57,6 +57,11 @@ 43 T2C2 35 + + 4 + 73 + CA62 + 7
diff --git a/templates/standalone/sortable.julius b/templates/standalone/sortable.julius index 5125c7204..4b988e487 100644 --- a/templates/standalone/sortable.julius +++ b/templates/standalone/sortable.julius @@ -1,88 +1,107 @@ /** * 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() { - - 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); + Array.from(document.querySelectorAll('.js-sortable')).forEach(function(table) { + utils.sortable(table); }); });