📊 Assistance par stade — MLB Stats API · MLB · 2025
# Stade % Remplissage Par match Total saison Capacité Matchs
Stadr
🎮Jeux
ℹ️À propos
var _ATT_TITLES = { fr: '📊 Assistance par stade — MLB Stats API · MLB · ', en: '📊 Attendance by Ballpark — MLB Stats API · MLB · ', es: '📊 Asistencia por estadio — MLB Stats API · MLB · ' }; var _ATT_SUBTITLES = { fr: 'Source : MLB Stats API · Saison régulière uniquement · Dernière mise à jour : mai 2026', en: 'Source: MLB Stats API · Regular season only · Last updated: May 2026', es: 'Fuente: MLB Stats API · Solo temporada regular · Última actualización: mayo 2026' }; function updatePageTitle(lg) { var el = document.getElementById('pageTitle'); if (!el) return; var sub = document.getElementById('pageSubtitle'); if (sub) sub.textContent = _ATT_SUBTITLES[lg] || _ATT_SUBTITLES['fr']; var base = _ATT_TITLES[lg] || _ATT_TITLES['fr']; var yrs = Array.from(_selectedYears).sort(function(a, b) { return a - b; }); var yearStr; if (yrs.length === 1) { yearStr = yrs[0]; } else if (yrs.length <= 4) { yearStr = yrs.join(', '); } else { yearStr = yrs[0] + '–' + yrs[yrs.length - 1]; } el.textContent = base + yearStr; } /* Language selector */ function langGlobeToggle(e) { e.stopPropagation(); document.getElementById('langGlobeWrap').classList.toggle('open'); } function langSelect(lg) { localStorage.setItem('lang', lg); document.getElementById('langCurrent').textContent = lg.toUpperCase(); document.querySelectorAll('#langGlobeMenu .lang-btn').forEach(function(b) { b.classList.toggle('active', b.getAttribute('data-lang') === lg); }); document.getElementById('langGlobeWrap').classList.remove('open'); updatePageTitle(lg); document.documentElement.lang = lg; var _md={fr:"Assistance MLB dans les 30 stades : taux de remplissage, moyenne par match, assistance totale et capacité. Données MLB Stats API.",en:"MLB attendance for all 30 ballparks: fill rate, average per game, total attendance and capacity. Data from MLB Stats API.",es:"Asistencia MLB en los 30 estadios: tasa de ocupación, promedio por partido, asistencia total y capacidad. Datos de MLB Stats API."}; var _me=document.querySelector('meta[name="description"]');if(_me&&_md[lg])_me.setAttribute('content',_md[lg]); } document.addEventListener('click', function() { var w = document.getElementById('langGlobeWrap'); if (w) w.classList.remove('open'); }); (function() { var lg = localStorage.getItem('lang') || 'fr'; document.getElementById('langCurrent').textContent = lg.toUpperCase(); document.querySelectorAll('#langGlobeMenu .lang-btn').forEach(function(b) { b.classList.toggle('active', b.getAttribute('data-lang') === lg); }); })(); /* Auth section */ var _sb = null; (function() { var SUPABASE_URL = 'https://bimedfhsdjxdbwnwozzp.supabase.co'; var SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImJpbWVkZmhzZGp4ZGJ3bndvenpwIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzM5NjUxODIsImV4cCI6MjA4OTU0MTE4Mn0.p6ccBlvVaXbw_quuuO1PsJIMkOzd6_PoqhxHSSHFq0E'; if (typeof window.supabase === 'undefined' || !window.supabase.createClient) return; _sb = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY); _sb.auth.getSession().then(function(res) { var session = res.data && res.data.session; if (!session) return; _sb.from('profiles').select('display_name,username,avatar_url').eq('id', session.user.id).single() .then(function(r) { var p = r.data || {}; var name = p.display_name || p.username || session.user.email.split('@')[0]; var inner = p.avatar_url ? 'avatar' : ''; document.getElementById('authSection').innerHTML = '
' + '
' + inner + '
' + '
' + '
👤 Mon profil
' + '
⚙️ Paramètres
' + '
🚪 Déconnexion
' + '
'; }); }); })(); function toggleUserDropdown(el) { var dd = el.querySelector('.user-dropdown'); if (!dd) return; dd.classList.toggle('open'); setTimeout(function() { document.addEventListener('click', function closeDD(e) { if (!e.target.closest('.user-menu')) { dd.classList.remove('open'); document.removeEventListener('click', closeDD); } }); }, 10); } function handleLogout() { if (_sb) _sb.auth.signOut().then(function() { window.location.href = 'login.html'; }); } /* Build stade id lookup by venue name */ var _stadeByName = {}; (function() { var stades = (typeof STADES !== 'undefined' ? STADES : []).filter(function(s) { return s.league === 'MLB'; }); stades.forEach(function(s) { _stadeByName[s.name] = s; }); })(); var SEASONS = [2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025]; // Première année MLB pour les stades ouverts dans la plage 2015-2025 var VENUE_MLB_FROM = { 'truist-park': 2017, // Braves quittent Turner Field 'globe-life-field': 2020, // Rangers quittent Globe Life Park in Arlington 'sutter-health-park': 2025 // A's quittent Oakland Coliseum }; function buildYearPills() { var container = document.getElementById('yearPills'); if (!container) return; var html = ''; SEASONS.forEach(function(yr) { var active = _selectedYears.has(yr) ? ' active' : ''; var covid = yr === 2020 ? ' covid' : ''; html += ''; }); container.innerHTML = html; } function toggleYear(yr) { if (_selectedYears.has(yr)) { if (_selectedYears.size === 1) return; _selectedYears.delete(yr); } else { _selectedYears.add(yr); } buildYearPills(); applyYearFilter(); } function applyYearFilter() { _rows = []; Object.keys(_historyData).forEach(function(slug) { var base = _attData2025[slug]; if (!base) return; var seasonArr = _historyData[slug]; if (!seasonArr) return; var filtered = seasonArr.filter(function(r) { return _selectedYears.has(r.season); }); if (!filtered.length) return; var nonCovid = filtered.filter(function(r) { return !r.covid; }); var totalTotal = filtered.reduce(function(s, r) { return s + (r.total || 0); }, 0); var totalGames = filtered.reduce(function(s, r) { return s + (r.games || 0); }, 0); var avgPerGame = nonCovid.length ? Math.round(nonCovid.reduce(function(s, r) { return s + (r.per_game || 0); }, 0) / nonCovid.length) : 0; var fillPcts = nonCovid .filter(function(r) { return r.fill_pct !== null && r.fill_pct !== undefined; }) .map(function(r) { return r.fill_pct; }); var avgFillPct = fillPcts.length ? +(fillPcts.reduce(function(s, v) { return s + v; }, 0) / fillPcts.length).toFixed(1) : null; var selectedArr = Array.from(_selectedYears); var displayName = base.stadium; if (selectedArr.length === 1) { var yr = selectedArr[0]; // Stade qui n'existait pas encore cette année → ne pas afficher var mlbFrom = VENUE_MLB_FROM[slug]; if (mlbFrom && yr < mlbFrom) return; // Afficher le nom réel du venue pour cette année var entry = filtered[0]; if (entry && entry.venue_name) displayName = entry.venue_name; } var stade = _stadeByName[base.stadium]; _rows.push({ stadium: displayName, team: base.team, capacity: base.capacity, per_game: avgPerGame, fill_pct: avgFillPct, total: totalTotal, games: totalGames, rank: null, _stadeId: stade ? stade.id : null }); }); var byFill = _rows.slice().sort(function(a, b) { return (b.fill_pct || 0) - (a.fill_pct || 0); }); byFill.forEach(function(r, i) { r.rank = i + 1; }); var lg = localStorage.getItem('lang') || 'fr'; updatePageTitle(lg); buildTable(); } /* Load both attendance JSONs in parallel */ Promise.all([ fetch('js/data/stadiums_attendance.json').then(function(r) { return r.ok ? r.json() : null; }), fetch('js/data/stadiums_attendance_history.json').then(function(r) { return r.ok ? r.json() : null; }) ]).then(function(results) { var att2025 = results[0]; var history = results[1]; if (!att2025 || !history) throw new Error('missing data'); _attData2025 = att2025; _historyData = history; var yf = document.getElementById('yearFilter'); if (yf) yf.style.display = ''; buildYearPills(); applyYearFilter(); }).catch(function() { document.getElementById('attBody').innerHTML = '' + 'Données non disponibles — rouler node scripts/fetch-attendance.js' + ''; });