covid19/tmpl/master.pug
2020-04-27 08:54:26 -07:00

248 lines
5.8 KiB
Plaintext

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);
}());