let deathsDataURL = "https://beta.ctvnews.ca/content/dam/common/exceltojson/COVID-19-Deaths.txt";
let canadaDataURL = "https://beta.ctvnews.ca/content/dam/common/exceltojson/COVID-19-Canada-New.txt";
function imageConvert(url, size = 300) {
let start = url.split("_gen")[0];
let fileType = start.split("image.")[1];
if (!fileType) {
return false;
}
let end = `_gen/derivatives/landscape_${size}/image.${fileType}`;
return start + end;
}
function build(deathsData, canadaData) {
/* Filter out blanks in death JSON */
deathsData = deathsData.filter((person) => person.Name);
/* Create array of province names and total deaths */
const provInfo = [
{ short: "BC", long: "British Columbia", deaths: 0 },
{ short: "AB", long: "Alberta", deaths: 0 },
{ short: "SK", long: "Saskatchewan", deaths: 0 },
{ short: "MB", long: "Manitoba", deaths: 0 },
{ short: "ON", long: "Ontario", deaths: 0 },
{ short: "QC", long: "Quebec", deaths: 0 },
{ short: "NB", long: "New Brunswick", deaths: 0 },
{ short: "NS", long: "Nova Scotia", deaths: 0 },
{ short: "PE", long: "Prince Edward Island", deaths: 0 },
{ short: "NL", long: "Newfoundland and Labrador", deaths: 0 },
{ short: "YT", long: "Yukon", deaths: 0 },
{ short: "NT", long: "Northwest Territories", deaths: 0 },
{ short: "NU", long: "Nunavut", deaths: 0 },
{ short: "Can", long: "Canada", deaths: 0 },
];
let currentDate;
function date2ms(d) {
let date = new Date(Math.round((d - 25569) * 864e5));
date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
return date;
}
function totalDeaths() {
let filteredBlanks = canadaData.filter((day) => day.Date);
let filteredData = filteredBlanks.filter(
(day, i) => i >= filteredBlanks.length - 2
);
currentDate = date2ms(filteredData[1].Date).toLocaleDateString();
provInfo.forEach((province) => {
let deathsToday = Number(filteredData[1][`${province.short}_Death`]);
let deathsYesterday = Number(filteredData[0][`${province.short}_Death`]);
province.deaths = deathsToday > 0 ? deathsToday : deathsYesterday;
});
}
totalDeaths();
console.log(currentDate);
console.log(provInfo);
/* End deaths calculation */
let page = d3.select(".obit-grid");
page.selectAll("*").remove();
deathsData.forEach((obj, i) => {
let obit = page.append("div").attr("class", "obit");
let nameSearch = document.querySelector("input.name");
let provinceSearch = document.querySelector("select.province");
function filterNames() {
if (obj.Name.toLowerCase().includes(nameSearch.value.toLowerCase())) {
return true;
} else {
return false;
}
}
function filterProvince() {
if (
!provinceSearch.value ||
obj.Province.toLowerCase() === provinceSearch.value.toLowerCase()
) {
return true;
} else {
return false;
}
}
function checkFilters() {
if (filterNames() && filterProvince()) {
obit.style("display", "block");
} else {
obit.style("display", "none");
}
}
nameSearch.addEventListener("input", function () {
checkFilters();
});
provinceSearch.addEventListener("change", function () {
checkFilters();
});
let image;
let src = imageConvert(obj.Photo_URL);
if (src) {
image = obit.append("img").attr("class", "obit-img").attr("src", src);
if (obj.Image_align !== "") {
image.style("object-position", `${obj.Image_align}% 50%`);
}
if (i > 12) {
image.attr("loading", "lazy");
}
} else {
image = obit.append("div").attr("class", "obit-img");
}
let name = obit
.append("div")
.attr("class", "obit-name bold")
.text(obj.Name + (Number(obj.Age) ? ", " + Number(obj.Age) : ""));
let location = obit
.append("div")
.attr("class", "obit-location light")
.text(
obj.Lived
? obj.Province
? `${obj.Lived}, ${obj.Province}`
: obj.Lived
: obj.Province
? obj.Province
: ""
);
let padding = 0;
let details = obit.append("div").attr("class", "obit-details");
details.append("div").attr("class", "obit-line");
let text = details
.append("div")
.attr("class", "obit-text")
.text(obj.Blurb)
.style("padding", `0 ${padding}px`);
details.append("div").attr("class", "obit-line");
let link = details
.append("a")
.text(`Read more >`)
.attr("class", "obit-link bold")
.attr("target", "_blank")
.attr("href", obj.Article_URL);
let open = false;
obit.on("click", () => {
details.style("height", (open ? 0 : details.node().scrollHeight) + "px");
obit.style("background", open ? "none" : "#fdfdfd");
obit.style("box-shadow", `0 0 0 ${open ? 0 : 1}px #f0f0f0`);
open = !open;
});
obit.on("mouseover", () => {
obit.style("background", "#fdfdfd");
obit.style("box-shadow", "0 0 0 1px #f0f0f0");
});
obit.on("mouseout", () => {
obit.style("background", open ? "#fdfdfd" : "none");
obit.style("box-shadow", `0 0 0 ${open ? 1 : 0}px #f0f0f0`);
});
});
return [currentDate, provInfo];
}
window.onload = () => {
let articleBody = document.querySelector(".articleBody");
articleBody.style.width = "100%";
articleBody.style.marginLeft = 0;
articleBody.style.marginRight = 0;
let loadingArray = document.querySelectorAll(".loading");
Array.from(loadingArray).forEach((div) => div.classList.remove("loading"));
Promise.all([d3.json(deathsDataURL), d3.json(canadaDataURL)]).then(
(files) => {
let [currentDate, provInfo] = build(files[0], files[1]);
let stats = {
date: currentDate,
deaths: provInfo
.find((prov) => prov.short === "Can")
.deaths.toLocaleString(),
};
let statsArray = [
`As of ${stats.date}, there have been ${stats.deaths} deaths in Canada from COVID-19`,
];
let statArray = document.querySelectorAll(".stat-line");
setTimeout(() => {
Array.from(statArray).forEach((div, i) => {
div.innerHTML = statsArray[i];
div.style.color = "#222";
});
}, 200);
let max = d3.max(
provInfo.filter((prov) => prov.short !== "Can"),
(d) => d.deaths
);
let colorRange = d3
.scaleLinear()
.domain([0, 1, max])
.range(["#e3e3e3", "#ffdbd9", "#ff4134"]);
provInfo.forEach((province) => {
Array.from(document.querySelectorAll(`.${province.short}`)).forEach(
(element) => {
if (element.tagName === "text") {
element.textContent = province.deaths.toLocaleString();
} else if (element.tagName === "path") {
element.setAttribute("fill", colorRange(province.deaths));
}
}
);
});
}
);
};