extends ./master.pug mixin sortableLinks(col, label) span.sortables.float-left.mr-2.d-inline-flex.flex-column(style="font-size: 50%") a(href="#sort:" + col + ":asc") ▲ a(href="#sort:" + col + ":desc") ▼ block block main h2 Country Rollup div#table.table-responsive: table.table.table-sm.table-hover thead: tr th # th: +sortableLinks("name") Country th: +sortableLinks("total") Deaths th: +sortableLinks("yesterday") …since yesterday th: +sortableLinks("week") …since last week th: +sortableLinks("month") …month-to-date th Last 14 days - data.sort((a, b) => { const yesterdayA = a.timeSeriesDaily[a.timeSeriesDaily.length - 1].delta; const yesterdayB = b.timeSeriesDaily[b.timeSeriesDaily.length - 1].delta; if (yesterdayA === yesterdayB) { return a.name.localeCompare(b.name); } return yesterdayA < yesterdayB ? 1 : -1; }); tbody: each item, i in data - const yesterday = item.timeSeriesDaily[item.timeSeriesDaily.length - 1].delta || 0; - const lastWeek = item.timeSeriesDaily[item.timeSeriesDaily.length - 1].value - item.timeSeriesDaily[item.timeSeriesDaily.length - 7].value; - const lastMonth = item.timeSeriesMonthly[item.timeSeriesMonthly.length - 1].delta || 0; tr(id="row-" + item.safeName data-name=item.name data-total=item.total data-yesterday=yesterday data-week=lastWeek data-month=lastMonth) td.sort-order= i + 1 td: a(href="./countries/" + item.safeName + ".html")= item.name td.text-right: +formatNumber(item.total) td.text-right: +formatNumber(yesterday) td.text-right: +formatNumber(lastWeek) td.text-right: +formatNumber(lastMonth) td canvas(id="sparkline-" + i width="200" height="50") script. (function() { const canvas = document.getElementById('sparkline-#{i}'); const chart = new Chart(canvas.getContext('2d'), { type: 'line', data: { labels: [ 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14 ], datasets: [ { data: #{JSON.stringify(item.timeSeriesDaily.slice(-14).map(x => x.value))}, } ], }, options: { responsive: false, legend: { display: false, }, elements: { line: { borderColor: '#000000', borderWidth: 1, }, point: { radius: 0, }, }, tooltips: { enabled: false, }, scales: { yAxes: [ { display: false, ticks: { precision: 0, beginAtZero: true, } }, ], xAxes: [ { display: false, }, ], } } }); }()); script. (function() { const tbody = document.getElementById('table').querySelector('tbody'); const allRows = [].slice.call(tbody.querySelectorAll('tbody tr')); const resortTable = () => { let nextChild = null; for (let i = allRows.length - 1; i >= 0; i--) { const row = allRows[i]; if (!row) { continue; } if (row === nextChild) { continue; } tbody.insertBefore(row, nextChild); row.querySelector('.sort-order').textContent = (i + 1).toString(); nextChild = row; } }; const handleSort = (value, dir) => { const newSortDir = dir === 'desc' ? 'desc' : 'asc'; const sortByNumberThenName = (attr) => { allRows.sort((a, b) => { const aValue = Number(a.getAttribute('data-' + attr)); const bValue = Number(b.getAttribute('data-' + attr)); if (aValue === bValue) { const aName = a.getAttribute('data-name'); const bName = b.getAttribute('data-name'); return aName.localeCompare(bName); } return aValue < bValue ? (newSortDir === 'asc' ? -1 : 1) : (newSortDir === 'asc' ? 1 : -1); }); resortTable(); }; switch (value) { case 'name': allRows.sort((a, b) => { const aName = a.getAttribute('data-name'); const bName = b.getAttribute('data-name'); if (newSortDir === 'asc') { return aName.localeCompare(bName); } return bName.localeCompare(aName); }); resortTable(); break; case 'total': sortByNumberThenName('total'); break; case 'yesterday': sortByNumberThenName('yesterday'); break; case 'week': sortByNumberThenName('week'); break; case 'month': sortByNumberThenName('month'); break; } }; const handleHash = (hash) => { const sortValue = hash.replace(/^#sort:/, '').split(':'); handleSort(sortValue[0], sortValue[1]); }; window.addEventListener('hashchange', () => { handleHash(window.location.hash); }); handleHash(window.location.hash || '#sort:yesterday:desc'); }());