|
239 | 239 | flex-shrink: 0; |
240 | 240 | } |
241 | 241 |
|
| 242 | + .fair-medal-overflow { |
| 243 | + font-size: 12px; |
| 244 | + font-weight: 800; |
| 245 | + color: rgba(255,255,255,0.7); |
| 246 | + align-self: flex-end; |
| 247 | + margin-left: 2px; |
| 248 | + } |
| 249 | +
|
242 | 250 | .fair-note { |
243 | 251 | text-align: center; |
244 | 252 | margin-top: 22px; |
|
385 | 393 | function bindControls() { |
386 | 394 | d3.select("#fair-season").on("change", function () { |
387 | 395 | state.season = this.value; |
| 396 | + state.rankingSeason = this.value; |
388 | 397 |
|
389 | 398 | const years = getAvailableYears(state.season); |
390 | 399 | if (!years.includes(state.year)) { |
391 | 400 | state.year = years[years.length - 1] || null; |
392 | 401 | } |
| 402 | + if (!years.includes(state.rankingYear)) { |
| 403 | + state.rankingYear = years[years.length - 1] || null; |
| 404 | + } |
393 | 405 |
|
394 | 406 | updateCountriesAfterSeasonOrYearChange(); |
395 | 407 | populateControls(); |
396 | 408 | render(); |
| 409 | + |
| 410 | + const rankingSeasonEl = document.getElementById("fair-ranking-season"); |
| 411 | + if (rankingSeasonEl) rankingSeasonEl.value = this.value; |
397 | 412 | }); |
398 | 413 |
|
399 | 414 | d3.select("#fair-year").on("change", function () { |
400 | 415 | state.year = Number(this.value); |
| 416 | + state.rankingYear = Number(this.value); |
401 | 417 |
|
402 | 418 | updateCountriesAfterSeasonOrYearChange(); |
403 | 419 | populateControls(); |
404 | 420 | render(); |
| 421 | + |
| 422 | + const rankingYearEl = document.getElementById("fair-ranking-year"); |
| 423 | + if (rankingYearEl) rankingYearEl.value = this.value; |
405 | 424 | }); |
406 | 425 |
|
407 | 426 | d3.select("#fair-country-1").on("change", function () { |
|
773 | 792 | grid.append("div").html(renderCountryCard(state.country1, data1, maxScale)); |
774 | 793 | grid.append("div").html(renderCountryCard(state.country2, data2, maxScale)); |
775 | 794 | renderRankingTable(); |
| 795 | + requestAnimationFrame(measureIconOverflow); |
776 | 796 | } |
777 | 797 |
|
778 | 798 | function renderMedalIcons(value, color) { |
|
783 | 803 | const full = Array(fullCount).fill(0).map(() => |
784 | 804 | `<div class="fair-medal-icon" style="background:${color}"></div>` |
785 | 805 | ).join(""); |
786 | | - |
787 | 806 | const half = hasHalf |
788 | 807 | ? `<div class="fair-medal-half-wrap"><div class="fair-medal-icon" style="background:${color}"></div></div>` |
789 | 808 | : ""; |
790 | 809 |
|
791 | | - return `<div class="fair-medal-icons">${full}${half}</div>`; |
| 810 | + return `<div class="fair-medal-icons" data-total="${rounded}">${full}${half}</div>`; |
| 811 | + } |
| 812 | + |
| 813 | + function measureIconOverflow() { |
| 814 | + document.querySelectorAll(".fair-medal-icons").forEach(container => { |
| 815 | + container.querySelectorAll(".fair-medal-overflow").forEach(el => el.remove()); |
| 816 | + |
| 817 | + const ROW_HEIGHT = 16; |
| 818 | + const GAP = 3; |
| 819 | + const MAX_ROWS = 2; |
| 820 | + const maxH = MAX_ROWS * ROW_HEIGHT + (MAX_ROWS - 1) * GAP; |
| 821 | + |
| 822 | + if (container.scrollHeight <= maxH + 1) return; |
| 823 | + |
| 824 | + const total = parseFloat(container.dataset.total) || 0; |
| 825 | + const iconW = ROW_HEIGHT + GAP; |
| 826 | + const containerW = container.clientWidth; |
| 827 | + const iconsPerRow = Math.max(1, Math.floor((containerW + GAP) / iconW)); |
| 828 | + const maxVisible = iconsPerRow * MAX_ROWS; |
| 829 | + |
| 830 | + const icons = Array.from(container.children).filter( |
| 831 | + el => el.classList.contains("fair-medal-icon") || el.classList.contains("fair-medal-half-wrap") |
| 832 | + ); |
| 833 | + |
| 834 | + icons.slice(maxVisible).forEach(el => el.style.display = "none"); |
| 835 | + |
| 836 | + const hidden = Math.ceil(total - maxVisible); |
| 837 | + if (hidden > 0) { |
| 838 | + const label = document.createElement("span"); |
| 839 | + label.className = "fair-medal-overflow"; |
| 840 | + label.textContent = `+${hidden}`; |
| 841 | + container.appendChild(label); |
| 842 | + } |
| 843 | + }); |
792 | 844 | } |
793 | 845 |
|
794 | 846 | function renderCountryCard(country, data, maxScale) { |
|
951 | 1003 |
|
952 | 1004 | d3.select("#fair-ranking-season").on("change", function () { |
953 | 1005 | state.rankingSeason = this.value; |
| 1006 | + state.season = this.value; |
| 1007 | + |
954 | 1008 | const newYears = getAvailableYears(state.rankingSeason); |
955 | 1009 | state.rankingYear = newYears.includes(state.rankingYear) |
956 | 1010 | ? state.rankingYear |
957 | 1011 | : newYears[newYears.length - 1]; |
| 1012 | + if (!newYears.includes(state.year)) { |
| 1013 | + state.year = newYears[newYears.length - 1] || null; |
| 1014 | + } |
| 1015 | + |
958 | 1016 | renderRankingTable(); |
| 1017 | + |
| 1018 | + const fairSeasonEl = document.getElementById("fair-season"); |
| 1019 | + if (fairSeasonEl) { |
| 1020 | + fairSeasonEl.value = this.value; |
| 1021 | + updateCountriesAfterSeasonOrYearChange(); |
| 1022 | + populateControls(); |
| 1023 | + render(); |
| 1024 | + } |
959 | 1025 | }); |
960 | 1026 |
|
961 | 1027 | d3.select("#fair-ranking-year").on("change", function () { |
962 | 1028 | state.rankingYear = Number(this.value); |
| 1029 | + state.year = Number(this.value); |
| 1030 | + |
963 | 1031 | renderRankingTable(); |
| 1032 | + |
| 1033 | + const fairYearEl = document.getElementById("fair-year"); |
| 1034 | + if (fairYearEl) { |
| 1035 | + fairYearEl.value = this.value; |
| 1036 | + updateCountriesAfterSeasonOrYearChange(); |
| 1037 | + populateControls(); |
| 1038 | + render(); |
| 1039 | + } |
964 | 1040 | }); |
965 | 1041 |
|
966 | 1042 | // Click highlight country |
|
0 commit comments