diff --git a/src/Handler/Home.hs b/src/Handler/Home.hs index 7180d87de..2d983e586 100644 --- a/src/Handler/Home.hs +++ b/src/Handler/Home.hs @@ -45,8 +45,10 @@ getHomeR = do defaultLayout $ do addStylesheet $ StaticR css_stickybar_css addStylesheet $ StaticR css_show_hide_css + addStylesheet $ StaticR css_sortable_css addScript $ StaticR js_stickybar_js addScript $ StaticR js_show_hide_js + addScript $ StaticR js_sortable_js setTitle "Willkommen zum ReWorX Test!" $(widgetFile "home") diff --git a/static/css/sortable.css b/static/css/sortable.css new file mode 100644 index 000000000..3299448a6 --- /dev/null +++ b/static/css/sortable.css @@ -0,0 +1,30 @@ +table.js-sortable th { + cursor: pointer; + position: relative; + padding-right: 20px; +} + +table.js-sortable th.sorted-asc, +table.js-sortable th.sorted-desc { + color: rebeccapurple; +} + +table.js-sortable th.sorted-asc::after, +table.js-sortable th.sorted-desc::after { + content: ''; + position: absolute; + right: 0; + width: 0; + height: 0; + top: 7px; + border-left: 8px solid transparent; + border-right: 8px solid transparent; +} + +table.js-sortable th.sorted-asc::after { + border-top: 8px solid rebeccapurple; +} + +table.js-sortable th.sorted-desc::after { + border-bottom: 8px solid rebeccapurple; +} diff --git a/static/js/sortable.js b/static/js/sortable.js new file mode 100644 index 000000000..4c553bd70 --- /dev/null +++ b/static/js/sortable.js @@ -0,0 +1,89 @@ +/** + * 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) { + console.log('initTable for ', table); + 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); + }); +}); diff --git a/templates/home.hamlet b/templates/home.hamlet index 0ea077d62..bac9e640b 100644 --- a/templates/home.hamlet +++ b/templates/home.hamlet @@ -39,6 +39,37 @@
  • Dateien hochladen und abrufen + +
    + + + + + + + + +
    ID + TH1 + TH2 + TH3 +
    0 + 14 + CON2 + 3 +
    1 + 5 + ONT2 + 13 +
    2 + CONT1 + NT2 + 43 +
    3 + 43 + T2C2 + 35 +

    Funktionen zum Testen