<style>
.spl-table-wrap {
font-family: Arial, sans-serif;
max-width: 900px;
margin: 0 auto;
}
.spl-table-wrap[dir="rtl"] { font-family: 'Segoe UI', Tahoma, Arial, sans-serif; }
.spl-table-title {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 14px;
font-size: 18px;
font-weight: 700;
color: #1a1a2e;
}
.spl-table-title img { width: 32px; height: 32px; object-fit: contain; }
.spl-table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
background: #fff;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
}
.spl-table thead tr {
background: #1a6b3c;
color: #fff;
text-transform: uppercase;
font-size: 11px;
letter-spacing: 0.5px;
}
.spl-table th, .spl-table td {
padding: 10px 8px;
text-align: center;
white-space: nowrap;
}
.spl-table th:nth-child(2),
.spl-table td:nth-child(2) { text-align: left; padding-left: 6px; }
[dir="rtl"] .spl-table th:nth-child(2),
[dir="rtl"] .spl-table td:nth-child(2) { text-align: right; padding-left: 0; padding-right: 6px; }
.spl-table tbody tr {
border-bottom: 1px solid #f0f0f0;
transition: background 0.15s;
}
.spl-table tbody tr:hover { background: #f7faf8; }
.spl-team-cell {
display: flex;
align-items: center;
gap: 8px;
min-width: 160px;
}
[dir="rtl"] .spl-team-cell { flex-direction: row-reverse; justify-content: flex-end; }
.spl-team-cell img { width: 24px; height: 24px; object-fit: contain; flex-shrink: 0; }
.spl-rank { font-weight: 700; color: #444; width: 28px; }
.spl-pts { font-weight: 700; color: #1a6b3c; }
.spl-zone-champions { border-left: 4px solid #1a6b3c; }
.spl-zone-league { border-left: 4px solid #3498db; }
.spl-zone-relegation{ border-left: 4px solid #e74c3c; }
[dir="rtl"] .spl-zone-champions { border-left: none; border-right: 4px solid #1a6b3c; }
[dir="rtl"] .spl-zone-league { border-left: none; border-right: 4px solid #3498db; }
[dir="rtl"] .spl-zone-relegation{ border-left: none; border-right: 4px solid #e74c3c; }
.spl-legend {
margin-top: 10px;
font-size: 11px;
color: #888;
display: flex;
gap: 16px;
flex-wrap: wrap;
}
[dir="rtl"] .spl-legend { flex-direction: row-reverse; }
.spl-legend-dot {
display: inline-block;
width: 10px; height: 10px;
border-radius: 2px;
margin-right: 4px;
vertical-align: middle;
}
[dir="rtl"] .spl-legend-dot { margin-right: 0; margin-left: 4px; }
.spl-updated { font-size: 11px; color: #aaa; text-align: right; margin-top: 8px; }
[dir="rtl"] .spl-updated { text-align: left; }
.spl-loading { text-align: center; padding: 30px; color: #888; font-size: 14px; }
@media (max-width: 600px) {
.spl-hide-mobile { display: none; }
.spl-table th, .spl-table td { padding: 8px 4px; font-size: 12px; }
.spl-team-cell { min-width: 110px; }
}
</style>
<div class="spl-table-wrap" id="spl-classement-root">
<div class="spl-table-title">
<img src="https://a.espncdn.com/i/leaguelogos/soccer/500/682.png" alt="SPL" onerror="this.style.display='none'">
<span id="spl-cl-title">...</span>
</div>
<div id="spl-classement-content">
<div class="spl-loading" id="spl-cl-loading">...</div>
</div>
<div class="spl-updated" id="spl-classement-updated"></div>
</div>
<script>
(function() {
var I18N = {
fr: {
title: 'Classement Saudi Pro League',
col_rank: '#',
col_team: 'Équipe',
col_played: 'MJ',
col_wins: 'V',
col_draws: 'N',
col_losses: 'D',
col_gf: 'BP',
col_ga: 'BC',
col_gd: 'Diff',
col_pts: 'Pts',
zone_ucl: 'Ligue des Champions',
zone_afc: 'AFC',
zone_rel: 'Relégation',
loading: 'Chargement du classement...',
error: 'Données temporairement indisponibles.',
updated: 'Mis à jour : ',
dir: 'ltr'
},
en: {
title: 'Saudi Pro League Standings',
col_rank: '#',
col_team: 'Team',
col_played: 'MP',
col_wins: 'W',
col_draws: 'D',
col_losses: 'L',
col_gf: 'GF',
col_ga: 'GA',
col_gd: 'GD',
col_pts: 'Pts',
zone_ucl: 'Champions League',
zone_afc: 'AFC',
zone_rel: 'Relegation',
loading: 'Loading standings...',
error: 'Data temporarily unavailable.',
updated: 'Updated: ',
dir: 'ltr'
},
ar: {
title: 'ترتيب الدوري السعودي للمحترفين',
col_rank: '#',
col_team: 'الفريق',
col_played: 'لعب',
col_wins: 'ف',
col_draws: 'ت',
col_losses: 'خ',
col_gf: 'له',
col_ga: 'عليه',
col_gd: 'فرق',
col_pts: 'نقاط',
zone_ucl: 'دوري أبطال أوروبا',
zone_afc: 'كأس AFC',
zone_rel: 'الهبوط',
loading: 'جاري تحميل الترتيب...',
error: 'البيانات غير متوفرة مؤقتاً.',
updated: 'آخر تحديث: ',
dir: 'rtl'
}
};
function detectLang() {
var lang = document.documentElement.lang || '';
lang = lang.toLowerCase().split('-')[0].split('_')[0];
return I18N[lang] ? lang : 'fr';
}
var lang = detectLang();
var t = I18N[lang];
var root = document.getElementById('spl-classement-root');
root.setAttribute('dir', t.dir);
document.getElementById('spl-cl-title').textContent = t.title;
document.getElementById('spl-cl-loading').textContent = t.loading;
var ZONES = { champions: [1,2], league: [3,4,5], relegation: [16,17,18] };
function zoneClass(rank) {
if (ZONES.champions.indexOf(rank) !== -1) return 'spl-zone-champions';
if (ZONES.league.indexOf(rank) !== -1) return 'spl-zone-league';
if (ZONES.relegation.indexOf(rank) !== -1) return 'spl-zone-relegation';
return '';
}
function parseStandings(data) {
var teams = [];
var groups = data.children || [data];
groups.forEach(function(group) {
var entries = (group.standings || {}).entries || [];
entries.forEach(function(entry) {
var team = entry.team || {};
var logos = team.logos || [];
var logo = logos.length ? logos[0].href : '';
var stats = {};
(entry.stats || []).forEach(function(s) { stats[s.name] = s.value || 0; });
teams.push({
rank: Math.round(stats.rank || 0),
name: team.displayName || '',
shortName: team.abbreviation || '',
logo: logo,
played: Math.round(stats.gamesPlayed || 0),
wins: Math.round(stats.wins || 0),
draws: Math.round(stats.draws || 0),
losses: Math.round(stats.losses || 0),
goalsFor: Math.round(stats.pointsFor || 0),
goalsAgainst: Math.round(stats.pointsAgainst || 0),
goalDiff: Math.round(stats.pointDifferential || 0),
points: Math.round(stats.points || 0)
});
});
});
teams.sort(function(a,b) { return a.rank - b.rank; });
return teams;
}
function render(teams) {
var now = new Date();
var html = '<table class="spl-table"><thead><tr>'
+ '<th>' + t.col_rank + '</th>'
+ '<th>' + t.col_team + '</th>'
+ '<th>' + t.col_played + '</th>'
+ '<th>' + t.col_wins + '</th>'
+ '<th class="spl-hide-mobile">' + t.col_draws + '</th>'
+ '<th class="spl-hide-mobile">' + t.col_losses + '</th>'
+ '<th class="spl-hide-mobile">' + t.col_gf + '</th>'
+ '<th class="spl-hide-mobile">' + t.col_ga + '</th>'
+ '<th>' + t.col_gd + '</th>'
+ '<th>' + t.col_pts + '</th>'
+ '</tr></thead><tbody>';
teams.forEach(function(tm) {
var diff = tm.goalDiff > 0 ? '+' + tm.goalDiff : tm.goalDiff;
html += '<tr class="' + zoneClass(tm.rank) + '">'
+ '<td class="spl-rank">' + tm.rank + '</td>'
+ '<td><div class="spl-team-cell">'
+ '<img src="' + tm.logo + '" alt="' + tm.name + '" onerror="this.style.display=\'none\'">'
+ '<span>' + tm.name + '</span>'
+ '</div></td>'
+ '<td>' + tm.played + '</td>'
+ '<td>' + tm.wins + '</td>'
+ '<td class="spl-hide-mobile">' + tm.draws + '</td>'
+ '<td class="spl-hide-mobile">' + tm.losses + '</td>'
+ '<td class="spl-hide-mobile">' + tm.goalsFor + '</td>'
+ '<td class="spl-hide-mobile">' + tm.goalsAgainst + '</td>'
+ '<td>' + diff + '</td>'
+ '<td class="spl-pts">' + tm.points + '</td>'
+ '</tr>';
});
html += '</tbody></table>';
html += '<div class="spl-legend">'
+ '<span><span class="spl-legend-dot" style="background:#1a6b3c"></span>' + t.zone_ucl + '</span>'
+ '<span><span class="spl-legend-dot" style="background:#3498db"></span>' + t.zone_afc + '</span>'
+ '<span><span class="spl-legend-dot" style="background:#e74c3c"></span>' + t.zone_rel + '</span>'
+ '</div>';
document.getElementById('spl-classement-content').innerHTML = html;
document.getElementById('spl-classement-updated').textContent =
t.updated + now.toLocaleDateString() + ' ' + now.toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'});
}
function loadStandings() {
fetch('https://site.web.api.espn.com/apis/v2/sports/soccer/ksa.1/standings?t=' + Date.now())
.then(function(r) { return r.json(); })
.then(function(data) { render(parseStandings(data)); })
.catch(function() {
document.getElementById('spl-classement-content').innerHTML =
'<div class="spl-loading">' + t.error + '</div>';
});
}
/* Charger immédiatement puis rafraîchir toutes les 5 minutes */
loadStandings();
setInterval(loadStandings, 5 * 60 * 1000);
})();
</script>