Skip to content

Commit 2a43523

Browse files
committed
feat: create loading message to avoid confusion with no data available messages
1 parent cc43d8d commit 2a43523

8 files changed

Lines changed: 148 additions & 5 deletions

File tree

website/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ <h2>Which delegations tend to win medals, and which don't?</h2>
142142

143143
<div class="slide" data-anchor="medal-flow">
144144
<div id="medal-viz">
145-
<h3 class="medal-viz-title"></h3>
145+
<h3 class="medal-viz-title">Distribution of medals in Summer Olympics</h3>
146146

147147
<div class="medal-controls">
148148
<div>
@@ -175,7 +175,7 @@ <h4 class="medal-viz-subtitle"></h4>
175175
</div>
176176

177177
<div class="slide" data-anchor="never-medaled">
178-
<h3 class="never-medaled-viz-title"></h3>
178+
<h3 class="never-medaled-viz-title">Countries that have participated without ever winning a medal</h3>
179179

180180
<div id="never-medaled-viz"></div>
181181

website/js/body-types.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ import { AthleteRenderer } from "./AthleteRenderer.js";
4747
document.addEventListener("DOMContentLoaded", init);
4848

4949
async function init() {
50-
if (!document.querySelector(selectors.root)) return;
50+
const root = document.querySelector(selectors.root);
51+
if (!root) return;
52+
53+
showLoading(root);
5154

5255
try {
5356
const [rows] = await Promise.all([
@@ -65,6 +68,7 @@ import { AthleteRenderer } from "./AthleteRenderer.js";
6568
state.rows = rows;
6669
state.columns = detectColumns(rows);
6770

71+
removeLoading(root);
6872
setupControls();
6973
initializeState();
7074
refreshAllControls();
@@ -719,6 +723,19 @@ import { AthleteRenderer } from "./AthleteRenderer.js";
719723
return event || sport || "Unknown";
720724
}
721725

726+
function showLoading(root) {
727+
root.classList.add("is-loading");
728+
const div = document.createElement("div");
729+
div.className = "viz-loading";
730+
div.textContent = "Loading data, please wait…";
731+
root.appendChild(div);
732+
}
733+
734+
function removeLoading(root) {
735+
root.classList.remove("is-loading");
736+
root.querySelectorAll(".viz-loading").forEach(el => el.remove());
737+
}
738+
722739
function showError(message) {
723740
const mount = document.querySelector(selectors.podium);
724741
if (!mount) return;

website/js/delegations.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@
299299
document.addEventListener("DOMContentLoaded", init);
300300

301301
async function init() {
302-
if (!document.querySelector(selectors.root)) return;
302+
const root = document.querySelector(selectors.root);
303+
if (!root) return;
303304

304305
if (typeof d3 === "undefined") {
305306
showError("D3 is not loaded.");
@@ -311,12 +312,15 @@
311312
return;
312313
}
313314

315+
showLoading(root);
316+
314317
try {
315318
const rows = await d3.csv(DATA_PATH, d3.autoType);
316319

317320
state.rows = rows;
318321
state.columns = detectColumns(rows);
319322

323+
removeLoading(root);
320324
setupControls();
321325
setSeason("Summer");
322326
} catch (error) {
@@ -1253,6 +1257,19 @@
12531257
return tooltip;
12541258
}
12551259

1260+
function showLoading(root) {
1261+
root.classList.add("is-loading");
1262+
const div = document.createElement("div");
1263+
div.className = "viz-loading";
1264+
div.textContent = "Loading data, please wait…";
1265+
root.appendChild(div);
1266+
}
1267+
1268+
function removeLoading(root) {
1269+
root.classList.remove("is-loading");
1270+
root.querySelectorAll(".viz-loading").forEach(el => el.remove());
1271+
}
1272+
12561273
function showError(message) {
12571274
d3.select(selectors.root)
12581275
.selectAll("*")

website/js/fair-distribution.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636
const root = document.querySelector(selectors.root);
3737
if (!root) return;
3838

39+
showLoading(root);
40+
41+
const rankingRoot = document.querySelector("#fair-ranking-viz");
42+
if (rankingRoot) showLoading(rankingRoot);
43+
3944
try {
4045
const rows = await d3.csv(DATA_PATH, d3.autoType);
4146

@@ -44,6 +49,7 @@
4449

4550
ensureRequiredColumns();
4651
injectStyles();
52+
removeLoading(root);
4753
buildScaffold();
4854
initializeState();
4955
populateControls();
@@ -931,6 +937,23 @@
931937
return d3.format(",.0f")(value);
932938
}
933939

940+
function showLoading(root) {
941+
root.classList.add("is-loading");
942+
const slide = root.closest(".slide");
943+
if (slide) slide.classList.add("is-loading");
944+
const div = document.createElement("div");
945+
div.className = "fair-loading";
946+
div.textContent = "Loading data, please wait…";
947+
root.appendChild(div);
948+
}
949+
950+
function removeLoading(root) {
951+
root.classList.remove("is-loading");
952+
const slide = root.closest(".slide");
953+
if (slide) slide.classList.remove("is-loading");
954+
root.querySelectorAll(".fair-loading").forEach(el => el.remove());
955+
}
956+
934957
function showError(message) {
935958
const root = document.querySelector(selectors.root);
936959
if (!root) return;
@@ -941,6 +964,9 @@
941964
function renderRankingTable() {
942965
const root = d3.select("#fair-ranking-viz");
943966
if (root.empty()) return;
967+
root.classed("is-loading", false);
968+
const slide = root.node().closest(".slide");
969+
if (slide) slide.classList.remove("is-loading");
944970

945971
if (!state.rankingYear) {
946972
state.rankingSeason = state.season;

website/js/gender-evolution.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@
9292
if (!root) return;
9393
if (typeof d3 === "undefined") { showError("D3 is not loaded."); return; }
9494

95+
showLoading(root);
96+
9597
try {
9698
const raw = await d3.json(DATA_PATH);
9799

@@ -135,6 +137,7 @@
135137
);
136138

137139
state.sportColorScale = buildGlobalSportColorScale(state.dataBySeasonYear);
140+
removeLoading(root);
138141
setupControls();
139142
setSeason("Summer");
140143
} catch (error) {
@@ -816,6 +819,19 @@
816819
Error
817820
============================================================ */
818821

822+
function showLoading(root) {
823+
root.classList.add("is-loading");
824+
const div = document.createElement("div");
825+
div.className = "viz-loading";
826+
div.textContent = "Loading data, please wait…";
827+
root.appendChild(div);
828+
}
829+
830+
function removeLoading(root) {
831+
root.classList.remove("is-loading");
832+
root.querySelectorAll(".viz-loading").forEach(el => el.remove());
833+
}
834+
819835
function showError(message) {
820836
const root = d3.select(selectors.root);
821837

website/js/geopolitics-conflicts.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@
282282
return;
283283
}
284284

285+
showGeoLoading();
286+
285287
try {
286288
const [rows, worldGeo] = await Promise.all([
287289
d3.csv(DATA_PATH, d3.autoType),
@@ -303,6 +305,7 @@
303305
hasOlympicData: state.olympicYears.includes(event.year)
304306
}));
305307

308+
removeGeoLoading();
306309
ensureTooltip();
307310

308311
const initialYear = state.events[0]?.year || state.olympicYears[0];
@@ -988,9 +991,28 @@
988991
}
989992

990993
/* ============================================================
991-
Error
994+
Loading / Error
992995
============================================================ */
993996

997+
function showGeoLoading() {
998+
const root = document.querySelector(selectors.mapRoot);
999+
if (!root) return;
1000+
const slide = root.closest(".slide");
1001+
if (slide) slide.classList.add("is-loading");
1002+
const div = document.createElement("div");
1003+
div.className = "geo-loading";
1004+
div.textContent = "Loading data, please wait…";
1005+
root.appendChild(div);
1006+
}
1007+
1008+
function removeGeoLoading() {
1009+
document.querySelectorAll(".geo-loading").forEach(el => {
1010+
const slide = el.closest(".slide");
1011+
if (slide) slide.classList.remove("is-loading");
1012+
el.remove();
1013+
});
1014+
}
1015+
9941016
function showGeoError(message) {
9951017
d3.select(selectors.mapRoot)
9961018
.selectAll("*")

website/js/never-medaled.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@
265265
return;
266266
}
267267

268+
showLoading(root);
269+
268270
try {
269271
const [rows, worldGeo] = await Promise.all([
270272
d3.csv(DATA_PATH, d3.autoType),
@@ -276,6 +278,7 @@
276278
state.columns = detectColumns(rows);
277279

278280
injectStyles();
281+
removeLoading(root);
279282
injectControls(root);
280283
setupControls();
281284
setSeason("Summer");
@@ -1183,6 +1186,19 @@
11831186
return tooltip;
11841187
}
11851188

1189+
function showLoading(root) {
1190+
root.classList.add("is-loading");
1191+
const div = document.createElement("div");
1192+
div.className = "never-loading";
1193+
div.textContent = "Loading data, please wait…";
1194+
root.appendChild(div);
1195+
}
1196+
1197+
function removeLoading(root) {
1198+
root.classList.remove("is-loading");
1199+
root.querySelectorAll(".never-loading").forEach(el => el.remove());
1200+
}
1201+
11861202
function showError(message) {
11871203
const root = d3.select(selectors.root);
11881204

website/styles.css

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,35 @@ h4 {
397397
max-width: 280px;
398398
}
399399

400+
.viz-loading,
401+
.geo-loading,
402+
.fair-loading,
403+
.never-loading {
404+
font-family: "Elms Sans", sans-serif;
405+
color: rgba(255, 255, 255, 0.6);
406+
font-size: 18px;
407+
text-align: center;
408+
padding: 40px 20px;
409+
width: 100%;
410+
}
411+
412+
/* Hide controls, timebars, and subtitles while data is loading */
413+
#gender-viz.is-loading .gender-controls,
414+
#gender-viz.is-loading .gender-timeline,
415+
#gender-viz.is-loading h4,
416+
#medal-viz.is-loading .medal-controls,
417+
#medal-viz.is-loading .medal-timeline,
418+
#medal-viz.is-loading .medal-viz-subtitle,
419+
#bodytype-viz.is-loading .bodytype-controls,
420+
#fair-viz.is-loading .fair-controls,
421+
#fair-ranking-viz.is-loading .fair-ranking-controls,
422+
#never-medaled-viz.is-loading ~ .medal-timeline.never-timeline,
423+
.slide.is-loading .fair-viz-subtitle,
424+
.slide.is-loading .geo-viz-subtitle,
425+
.slide.is-loading .geo-country-hint {
426+
visibility: hidden;
427+
}
428+
400429
.gender-empty,
401430
.gender-error {
402431
font-family: "Elms Sans", sans-serif;

0 commit comments

Comments
 (0)