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