doctype html head title= $title + ' | Covid-19' meta(charset="utf8") link(rel="stylesheet" href="/bootstrap.css") script(src="/Chart.bundle.js") style. table td { vertical-align: middle !important; } th.sorted, td.sorted { background-color: #e0eefd; } .table-sm { font-size: 80%; } script. function makeSparkline(id, data) { const canvas = document.getElementById(id); 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: data }], }, 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, }, ], } } }); } function makeHeroChart(id, title, labels, totalDeaths, newDeaths) { const canvas = document.getElementById(id); const chart = new Chart(canvas.getContext('2d'), { type: 'line', data: { labels: labels, datasets: [ { label: 'Total Deaths', data: totalDeaths, fill: true, borderColor: 'rgb(196, 64, 64)', borderWidth: 1, backgroundColor: 'rgba(196, 128, 128, 0.25)', }, { label: 'New Deaths', data: newDeaths, fill: true, borderColor: 'rgb(64, 64, 64)', borderWidth: 1, backgroundColor: 'rgba(128, 128, 128, 0.75)', } ], }, options: { responsive: false, title: { display: true, position: 'top', text: title, }, tooltips: { intersect: false, position: 'nearest', axis: 'x', }, scales: { yAxes: [ { display: true, ticks: { precision: 0, beginAtZero: true, } }, ], xAxes: [ { display: true, }, ], } } }); } body mixin formatNumber(num) = Number(num).toLocaleString() mixin sortableLinks(col, label) div.d-inline-flex span.sortables.mr-2.d-inline-flex.flex-column(style="font-size: 50%") a(href="#sort:" + col + ":asc") ▲ a(href="#sort:" + col + ":desc") ▼ span block div.container h1 Covid-19 Data p.text-muted: em. Data from #[a(href="https://github.com/CSSEGISandData/COVID-19") Johns Hopkins CSSE]. This page generated from latest data as of #{new Date().toISOString()}. div.main-content block main script. (function() { const table = document.getElementById('table'); const headerRow = table.querySelector('thead tr'); const headers = [].slice.call(headerRow.querySelectorAll('th')); const tbody = table.querySelector('tbody'); const allRows = [].slice.call(tbody.querySelectorAll('tbody tr')); const resortTable = (col) => { let nextChild = null; const highlightedIndex = headers.findIndex(cell => cell.getAttribute('data-col') === col); console.log(col, highlightedIndex); headers.forEach((cell, i) => { if (i !== highlightedIndex) { cell.classList.remove('sorted'); } else { cell.classList.add('sorted'); } }); for (let i = allRows.length - 1; i >= 0; i--) { const row = allRows[i]; if (!row) { continue; } const cells = [].slice.call(row.querySelectorAll('td')); cells.forEach((cell, i) => { if (i !== highlightedIndex) { cell.classList.remove('sorted'); } else { cell.classList.add('sorted'); } }); 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 && bName ? aName.localeCompare(bName) : 0; } return aValue < bValue ? (newSortDir === 'asc' ? -1 : 1) : (newSortDir === 'asc' ? 1 : -1); }); resortTable(value); }; switch (value) { case 'name': allRows.sort((a, b) => { const aName = a.getAttribute('data-name'); const bName = b.getAttribute('data-name'); if (!aName || !bName) { return -1; } if (newSortDir === 'asc') { return aName.localeCompare(bName); } return bName.localeCompare(aName); }); resortTable('name'); 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); }());