|
| 1 | +(function () { |
| 2 | + let epssChartInstance = null; |
| 3 | + |
| 4 | + const [btnChart, btnTable, chartWrap, tableWrap] = |
| 5 | + ["btn-load-epss-chart", "btn-load-epss-table", "epss-chart-wrap", "epss-history-table-wrap"] |
| 6 | + .map(id => document.getElementById(id)); |
| 7 | + |
| 8 | + const getHistoryData = () => JSON.parse(document.getElementById('epss-history-data')?.textContent || "[]"); |
| 9 | + const toggleDisplay = (el) => el.style.display = el.style.display === "none" ? "block" : "none"; |
| 10 | + |
| 11 | + function renderChart() { |
| 12 | + const data = getHistoryData(); |
| 13 | + if (!data.length) return; |
| 14 | + |
| 15 | + toggleDisplay(chartWrap); |
| 16 | + if (chartWrap.style.display === "none" || epssChartInstance) return; |
| 17 | + |
| 18 | + const history = []; |
| 19 | + const map = new Map(data.map(h => [new Date(h.published_at + "T00:00:00").setHours(0,0,0,0), h])); |
| 20 | + |
| 21 | + const end = new Date(data[data.length - 1].published_at + "T00:00:00").setHours(0,0,0,0); |
| 22 | + let start = new Date(end); |
| 23 | + start.setDate(start.getDate() - 30); |
| 24 | + |
| 25 | + const actualStart = new Date(data[0].published_at + "T00:00:00").setHours(0,0,0,0); |
| 26 | + start = new Date(Math.max(start.getTime(), actualStart)); |
| 27 | + |
| 28 | + for (let d = start; d.getTime() <= end; d.setDate(d.getDate() + 1)) { |
| 29 | + history.push(map.get(d.getTime()) || { |
| 30 | + published_at: `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`, |
| 31 | + score: null, percentile: null |
| 32 | + }); |
| 33 | + } |
| 34 | + try { |
| 35 | + epssChartInstance = bb.generate({ |
| 36 | + bindto: "#epss-chart", |
| 37 | + size: { height: 260 }, padding: { right: 25 }, |
| 38 | + data: { |
| 39 | + x: "Date", xFormat: "%Y-%m-%d", |
| 40 | + columns: [ |
| 41 | + ["Date", ...history.map(h => h.published_at || "")], |
| 42 | + ["Score", ...history.map(h => h.score === null ? null : parseFloat(h.score))], |
| 43 | + ["Percentile", ...history.map(h => h.percentile === null ? null : parseFloat(h.percentile))], |
| 44 | + ], |
| 45 | + type: "line", colors: { Score: "#df25e6ff", Percentile: "#00d1b2" }, |
| 46 | + }, |
| 47 | + //Handles missing dates |
| 48 | + line: { connectNull: false }, |
| 49 | + axis: { |
| 50 | + x: { type: "timeseries", tick: { format: "%b %d", count: Math.min(history.length, 6), fit: true } }, |
| 51 | + y: { min: 0, max: 1, padding: { top: 10, bottom: 0 }, tick: { format: v => v.toFixed(4) } }, |
| 52 | + }, |
| 53 | + point: { r: 3 }, legend: { show: true }, |
| 54 | + tooltip: { |
| 55 | + format: { |
| 56 | + title: d => d instanceof Date ? `${d.toLocaleString('en-us', {month: 'short'})} ${String(d.getDate()).padStart(2, '0')}, ${d.getFullYear()}` : String(d), |
| 57 | + value: v => v.toFixed(5), |
| 58 | + }, |
| 59 | + }, |
| 60 | + }); |
| 61 | + } catch (e) { console.error("[epss-chart]", e); } |
| 62 | + } |
| 63 | + |
| 64 | + btnChart?.addEventListener("click", renderChart); |
| 65 | + btnTable?.addEventListener("click", () => toggleDisplay(tableWrap)); |
| 66 | +})(); |
0 commit comments