PageSourceSearch

https://global-plastics-tool.org/js/overview_scorecard.js?v=1754414513

js global-plastics-tool.org collected 2026-09-26 01:13:48 UTC 3,818 bytes, 126 lines download raw bytes

1/**
2 * Logic for overview scorecards.
3 *
4 * @license BSD, see LICENSE.md
5 */
6
7
8/**
9 * Presenter for the scorecards which show high level goal metrics on the overview tab.
10 */
11class ScorecardPresenter {
12    /**
13     * Create a new scorecard presenter.
14     *
15     * @param targetDiv Div in which the scorecards are rendered.
16     * @param onGoalChange Callback if the user changes the highlighted goal metric.
17     * @param prefix Flag indicating if the plus / minus sign should be forced to be shown.
18     */
19    constructor(targetDiv, onGoalChange, prefix) {
20        const self = this;
21
22        self._targetDiv = targetDiv;
23        self._onGoalChange = onGoalChange;
24        self._prefix = prefix;
25        self._tippyPrior = null;
26
27        self._targetDiv.querySelectorAll(".card").forEach((card) => {
28            card.addEventListener("click", () => {
29                card.querySelector(".overview-radio").checked = true;
30                self._onGoalChange(card.getAttribute("goal"));
31            });
32        });
33    }
34
35    /**
36     * Render the card or update it if already present.
37     *
38     * @param year Year for which the metrics are to be shown.
39     * @param goals The goal metric calculations.
40     * @param selectedGoal Goal currently highlighted by the user.
41     */
42    render(year, goals, selectedGoal) {
43        const self = this;
44
45        if (self._tippyPrior === null) {
46            // eslint-disable-next-line no-undef
47            self._tippyPrior = tippy(
48                self._targetDiv.querySelectorAll(".info-target"),
49            );
50        }
51
52        const updateYear = () => {
53            self._targetDiv.querySelector(".year").innerHTML = year;
54        };
55
56        const updateBody = () => {
57            const setBody = (cardClass, value) => {
58                const valueRounded = Math.round(value * 10) / 10;
59                const prefix = self._prefix && valueRounded >= 0 ? "+" : "";
60                const valueStr = prefix + valueRounded;
61
62                const target = self._getD3().select("#" + self._targetDiv.id)
63                    .select("." + cardClass)
64                    .select(".body");
65
66                if (target.text() !== valueStr) {
67                    target.text(valueStr);
68                    target.style("opacity", 0)
69                        .transition()
70                        .duration(750)
71                        .style("opacity", 1);
72                }
73            };
74
75            setBody(
76                "mismanaged-waste-card",
77                goals.get("global").get("mismanagedWaste"),
78            );
79
80            setBody(
81                "landfill-waste-card",
82                goals.get("global").get("landfillWaste"),
83            );
84
85            setBody(
86                "incinerated-waste-card",
87                goals.get("global").get("incineratedWaste"),
88            );
89
90            setBody(
91                "recycling-card",
92                goals.get("global").get("recycling"),
93            );
94
95            setBody(
96                "ghg-card",
97                goals.get("global").get("ghg"),
98            );
99        };
100
101        const updateHighlight = () => {
102            self._targetDiv.querySelectorAll(".card").forEach((card) => {
103                if (card.getAttribute("goal") === selectedGoal) {
104                    card.classList.add("active");
105                    card.querySelector(".overview-radio").checked = true;
106                } else {
107                    card.classList.remove("active");
108                    card.querySelector(".overview-radio").checked = false;
109                }
110            });
111        };
112
113        updateYear();
114        updateBody();
115        updateHighlight();
116    }
117
118    _getD3() {
119        const self = this;
120        // eslint-disable-next-line no-undef
121        return d3;
122    }
123}
124
125
126export {ScorecardPresenter};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.