# Player Pos G A PTS ↓ PIM

Goaltenders

# Player W L T GA GAA SO PIM
${teamData.W ?? '–'}Wins
${teamData.L ?? '–'}Losses
${teamData.T ?? 0}Ties
${teamData.GF ?? '–'}GF
${teamData.GA ?? '–'}GA
${diff>0?'+':''}${diff}Diff
`; // ── SKATERS ── let skaterSort = 'pts', skaterDir = 1; const teamSkaters = skaters.filter(s => s.Team === team); function colVal(p, col) { if (col === 'pos') return p.Pos === 'D' ? 1 : 0; return Number(p[{g:'G',a:'A',pts:'PTS',pim:'PIM'}[col]] ?? 0); } function renderSkaters() { if (!teamSkaters.length) { document.getElementById('skaters-body').innerHTML = 'No skaters found'; document.getElementById('skaters-foot').innerHTML = ''; return; } const sorted = [...teamSkaters].sort((a,b) => { if (skaterSort === 'pos') { const aIsG = a.Pos === 'G', bIsG = b.Pos === 'G'; // G always last if (aIsG !== bIsG) return aIsG ? 1 : -1; const aIsD = a.Pos === 'D', bIsD = b.Pos === 'D'; if (skaterDir === 1) { if (aIsD !== bIsD) return aIsD ? 1 : -1; } else { if (aIsD !== bIsD) return aIsD ? -1 : 1; } return Number(b.PTS||0) - Number(a.PTS||0); } // For all other sorts, always keep G at bottom const aIsG = a.Pos === 'G', bIsG = b.Pos === 'G'; if (aIsG !== bIsG) return aIsG ? 1 : -1; return skaterDir * (colVal(b,skaterSort) - colVal(a,skaterSort)); }); const highlightPTS = skaterSort === 'pts' || skaterSort === 'pos'; document.getElementById('skaters-body').innerHTML = sorted.map(p => ` ${p.Jersey||'–'} ${p.Name} ${p.Pos} ${p.G} ${p.A} ${p.PTS} ${p.PIM} `).join(''); // Totals row const tG = teamSkaters.reduce((s,p)=>s+Number(p.G||0),0); const tA = teamSkaters.reduce((s,p)=>s+Number(p.A||0),0); const tPTS = teamSkaters.reduce((s,p)=>s+Number(p.PTS||0),0); const tPIM = teamSkaters.reduce((s,p)=>s+Number(p.PIM||0),0); document.getElementById('skaters-foot').innerHTML = ` Total ${tG} ${tA} ${tPTS} ${tPIM} `; } // Wire up sortable headers document.querySelectorAll('#skaters-table th[data-col]').forEach(th => { th.style.cursor = 'pointer'; if (!th.dataset.label) th.dataset.label = th.textContent.trim(); th.addEventListener('click', () => { const col = th.dataset.col; const defaultDir = col === 'pos' ? -1 : 1; skaterDir = skaterSort === col ? skaterDir * -1 : defaultDir; skaterSort = col; document.querySelectorAll('#skaters-table th[data-col]').forEach(t => { t.classList.remove('sorted'); t.textContent = t.dataset.label; }); th.classList.add('sorted'); if (col === 'pos') { th.textContent = skaterDir === 1 ? 'Pos F↑' : 'Pos D↑'; } else { th.textContent = th.dataset.label + (skaterDir === -1 ? ' ↓' : ' ↑'); } renderSkaters(); }); }); renderSkaters(); // ── GOALIES ── const teamGoalies = goalies.filter(g => g.Team === team).sort((a,b) => { const aRental = (a.Name||'').toLowerCase().includes('rental'); const bRental = (b.Name||'').toLowerCase().includes('rental'); if (aRental !== bRental) return aRental ? 1 : -1; return a.GAA - b.GAA; }); if (!teamGoalies.length) { document.getElementById('goalies-body').innerHTML = 'No goalies found'; document.getElementById('goalies-foot').innerHTML = ''; } else { document.getElementById('goalies-body').innerHTML = teamGoalies.map(g => ` ${g.Jersey||'–'} ${g.Name} ${g.W}${g.L}${g.T??0} ${g.GA} ${Number(g.GAA).toFixed(2)} ${g.SO}${g.PIM} `).join(''); // Goalie totals const gW = teamGoalies.reduce((s,g)=>s+Number(g.W||0),0); const gL = teamGoalies.reduce((s,g)=>s+Number(g.L||0),0); const gT = teamGoalies.reduce((s,g)=>s+Number(g.T||0),0); const gGA = teamGoalies.reduce((s,g)=>s+Number(g.GA||0),0); const gSO = teamGoalies.reduce((s,g)=>s+Number(g.SO||0),0); const gPIM = teamGoalies.reduce((s,g)=>s+Number(g.PIM||0),0); const gGP = gW + gL + gT; const gGAA = gGP > 0 ? (gGA / gGP).toFixed(2) : '0.00'; document.getElementById('goalies-foot').innerHTML = ` Total ${gW} ${gL} ${gT} ${gGA} ${gGAA} ${gSO} ${gPIM} `; } } async function init() { const data = await loadData(); applyAwardsVisibility(data); _rosterData = data; const params = new URLSearchParams(window.location.search); let activeTeam = params.get('team') || 'Toronto'; if (!TEAMS.includes(activeTeam)) activeTeam = 'Toronto'; function buildSwitcher() { document.getElementById('team-switcher').innerHTML = TEAMS.map(t => ` `).join(''); } window.switchTeam = function(team) { activeTeam = team; _activeRosterTeam = team; history.replaceState(null,'',`?team=${encodeURIComponent(team)}`); buildSwitcher(); renderTeam(team, _rosterData); }; buildSwitcher(); renderTeam(activeTeam, _rosterData); } init(); // Apply dynamic season label from Google Sheet fetchSeason().then(s => { const label = s + ' Season'; document.querySelectorAll('.season-label').forEach(el => el.textContent = label); });