Spaces:
Runtime error
Runtime error
Upload static/match_detail.js
Browse files- static/match_detail.js +128 -79
static/match_detail.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
// === VNEWS — Match Detail UI ===
|
| 2 |
-
// Renders match detail (
|
| 3 |
-
// Integrates with app_v2.js openMatch / loadMatchTab
|
| 4 |
|
| 5 |
(function(){
|
| 6 |
if(window._mdLoaded) return;
|
|
@@ -13,6 +12,16 @@
|
|
| 13 |
s.textContent=`
|
| 14 |
.md-sec{margin-bottom:14px}
|
| 15 |
.md-sec-title{font-size:13px;font-weight:800;color:#5cb87a;margin-bottom:6px;padding-bottom:4px;border-bottom:1px solid #2a2a2a;display:flex;align-items:center;gap:6px}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
.md-preview-text{font-size:12px;color:#ccc;line-height:1.6;background:#1a1a1a;border-radius:8px;padding:10px;border-left:3px solid #2d8659;max-height:300px;overflow-y:auto}
|
| 17 |
.md-lineups{display:grid;grid-template-columns:1fr 1fr;gap:10px}
|
| 18 |
.md-team-box{background:#1a2a1f;border:1px solid #2a3a2a;border-radius:8px;padding:8px}
|
|
@@ -20,11 +29,29 @@
|
|
| 20 |
.md-formation{font-size:9px;color:#888;text-align:center;margin-bottom:6px}
|
| 21 |
.md-player-item{font-size:10px;color:#ccc;padding:2px 0;border-bottom:1px solid #1a2a1f}
|
| 22 |
.md-h2h-item{display:flex;align-items:center;gap:6px;padding:6px;background:#1a1a1a;border-radius:6px;margin-bottom:3px;font-size:11px}
|
| 23 |
-
.md-h2h-date{font-size:9px;color:#888;min-width:55px}
|
| 24 |
-
.md-h2h-
|
| 25 |
-
.md-h2h-
|
| 26 |
-
.md-h2h-
|
| 27 |
-
.md-h2h-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
.md-no-data{color:#777;font-size:12px;padding:16px;text-align:center}
|
| 29 |
.md-err{color:#e74c3c;font-size:12px;padding:16px;text-align:center}
|
| 30 |
.mo-tab-detail{}
|
|
@@ -34,12 +61,11 @@
|
|
| 34 |
|
| 35 |
function esc(s){return String(s||'').replace(/[&<>"']/g,function(m){return{'&':'&','<':'<','>':'>','"':'"',"'":'''}[m]})}
|
| 36 |
|
| 37 |
-
// === 1. Override openMatch to always set _currentEventId
|
| 38 |
const _origOpenMatch = window.openMatch;
|
| 39 |
window.openMatch = function(id){
|
| 40 |
if(id) window._currentEventId = String(id);
|
| 41 |
if(_origOpenMatch) _origOpenMatch.call(this, id);
|
| 42 |
-
// Switch to detail tab
|
| 43 |
setTimeout(function(){
|
| 44 |
injectDetailTab();
|
| 45 |
loadMatchTab('detail');
|
|
@@ -53,24 +79,19 @@
|
|
| 53 |
if(_origLoadMatchTab) _origLoadMatchTab.call(this, tab);
|
| 54 |
return;
|
| 55 |
}
|
| 56 |
-
|
| 57 |
-
// Update tab UI — highlight the Chi tiết tab
|
| 58 |
document.querySelectorAll('.mo-tab').forEach(function(t){ t.classList.remove('active'); });
|
| 59 |
document.querySelectorAll('.mo-tab').forEach(function(t){
|
| 60 |
const txt = t.textContent || '';
|
| 61 |
if(txt.includes('Chi tiết') || txt.includes('📋')) t.classList.add('active');
|
| 62 |
});
|
| 63 |
-
|
| 64 |
const el = document.getElementById('mo-body');
|
| 65 |
if(!el) return;
|
| 66 |
el.innerHTML = '<div class="md-no-data">⏳ Đang tải chi tiết trận đấu...</div>';
|
| 67 |
-
|
| 68 |
const eventId = window._currentEventId;
|
| 69 |
if(!eventId){
|
| 70 |
-
el.innerHTML = '<div class="md-err">⚠️ Không tìm thấy mã trận đấu.<
|
| 71 |
return;
|
| 72 |
}
|
| 73 |
-
|
| 74 |
try{
|
| 75 |
const r = await fetch('/api/match/' + eventId + '/detail');
|
| 76 |
if(!r.ok) throw new Error('API error ' + r.status);
|
|
@@ -86,92 +107,121 @@
|
|
| 86 |
function renderMatchDetail(el, data){
|
| 87 |
let h = '';
|
| 88 |
|
| 89 |
-
//
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
|
| 94 |
.replace(/<iframe[^>]*>[\s\S]*?<\/iframe>/gi, '')
|
| 95 |
.replace(/<ins[^>]*>[\s\S]*?<\/ins>/gi, '');
|
| 96 |
-
h += '<div class="md-preview-text">' + clean + '</div></div>';
|
| 97 |
-
} else if(data.preview_text && data.preview_text.length > 0){
|
| 98 |
h += '<div class="md-sec"><div class="md-sec-title">📋 Thông tin trận đấu</div>';
|
| 99 |
-
h += '<div class="md-preview-text">' +
|
| 100 |
}
|
| 101 |
|
| 102 |
-
//
|
| 103 |
-
if(data.
|
| 104 |
-
h += '<div class="md-sec"><div class="md-sec-title">
|
| 105 |
-
h += '<div
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
}
|
| 110 |
|
| 111 |
-
//
|
| 112 |
-
if(data.
|
| 113 |
-
h += '<div class="md-sec"><div class="md-sec-title">🔄
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
h += '<div>' + data.h2h_html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,'').replace(/<iframe[^>]*>[\s\S]*?<\/iframe>/gi,'') + '</div></div>';
|
| 115 |
-
} else if(data.h2h && data.h2h.length > 0){
|
| 116 |
-
h += '<div class="md-sec"><div class="md-sec-title">🔄 Đối đầu (H2H)</div>';
|
| 117 |
-
h += renderH2H(data.h2h) + '</div>';
|
| 118 |
}
|
| 119 |
|
| 120 |
-
//
|
| 121 |
-
if(data.
|
| 122 |
-
h += '<div class="md-sec"><div class="md-sec-title">
|
| 123 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
}
|
| 125 |
|
| 126 |
-
//
|
| 127 |
-
if(data.
|
| 128 |
-
h += '<div class="md-sec"><div class="md-sec-title">
|
| 129 |
-
h += '<div
|
| 130 |
-
if(data.info.date) h += '<div>📅 Ngày: <b>'+esc(data.info.date)+'</b></div>';
|
| 131 |
-
if(data.info.time) h += '<div>🕐 Giờ: <b>'+esc(data.info.time)+'</b></div>';
|
| 132 |
-
if(data.info.stadium) h += '<div>🏟 Sân: <b>'+esc(data.info.stadium)+'</b></div>';
|
| 133 |
-
if(data.info.referee) h += '<div>👨⚖️ Trọng tài: <b>'+esc(data.info.referee)+'</b></div>';
|
| 134 |
-
h += '</div></div>';
|
| 135 |
}
|
| 136 |
|
| 137 |
if(!h){
|
| 138 |
-
h = '<div class="md-no-data">Chưa có chi tiết cho trận đấu này.<br><small style="color:#666">Dữ liệu sẽ cập nhật khi giải khởi tranh hoặc trận đấu bắt đầu.</small></div>';
|
| 139 |
}
|
| 140 |
-
|
| 141 |
el.innerHTML = h;
|
| 142 |
-
// Prevent link navigation inside overlay
|
| 143 |
el.querySelectorAll('a').forEach(function(a){ a.addEventListener('click', function(e){ e.preventDefault(); }); });
|
| 144 |
}
|
| 145 |
|
| 146 |
-
function
|
| 147 |
-
let h='<div class="md-
|
| 148 |
-
h+='<
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
h+='</
|
| 153 |
-
h+='<
|
| 154 |
-
|
| 155 |
-
(l.away_players||[]).forEach(function(p,i){h+='<div class="md-player-item">'+(i+1)+'. '+esc(p)+'</div>';});
|
| 156 |
-
if(l.away_subs&&l.away_subs.length){h+='<div style="font-size:9px;color:#888;margin-top:6px;font-style:italic">Dự bị:</div>';(l.away_subs||[]).forEach(function(p){h+='<div style="font-size:9px;color:#888">'+esc(p)+'</div>';});}
|
| 157 |
-
h+='</div></div>';
|
| 158 |
-
return h;
|
| 159 |
-
}
|
| 160 |
-
|
| 161 |
-
function renderH2H(matches){
|
| 162 |
-
let h='';
|
| 163 |
-
matches.forEach(function(m){
|
| 164 |
-
h+='<div class="md-h2h-item">';
|
| 165 |
-
h+='<span class="md-h2h-date">'+esc(m.date||'')+'</span>';
|
| 166 |
-
h+='<span class="md-h2h-teams"><span class="md-h2h-home">'+esc(m.home||'')+'</span>';
|
| 167 |
-
h+='<span class="md-h2h-score">'+esc(m.score||'vs')+'</span>';
|
| 168 |
-
h+='<span class="md-h2h-away">'+esc(m.away||'')+'</span></span>';
|
| 169 |
-
h+='</div>';
|
| 170 |
-
});
|
| 171 |
return h;
|
| 172 |
}
|
| 173 |
|
| 174 |
-
// === 4. Inject "Chi tiết" tab
|
| 175 |
function injectDetailTab(){
|
| 176 |
const tabs = document.querySelector('.mo-tabs');
|
| 177 |
if(!tabs || document.querySelector('.mo-tab-detail')) return;
|
|
@@ -182,7 +232,7 @@
|
|
| 182 |
tabs.insertBefore(d, tabs.firstChild);
|
| 183 |
}
|
| 184 |
|
| 185 |
-
// === 5. Intercept clicks
|
| 186 |
document.addEventListener('click', function(e){
|
| 187 |
const md = e.target.closest('.match-detail');
|
| 188 |
if(!md) return;
|
|
@@ -194,7 +244,6 @@
|
|
| 194 |
}
|
| 195 |
}, true);
|
| 196 |
|
| 197 |
-
// Try to inject tab on DOM ready
|
| 198 |
if(document.readyState==='loading') document.addEventListener('DOMContentLoaded', function(){ setTimeout(injectDetailTab, 1000); });
|
| 199 |
else setTimeout(injectDetailTab, 1000);
|
| 200 |
})();
|
|
|
|
| 1 |
// === VNEWS — Match Detail UI ===
|
| 2 |
+
// Renders match detail (pre-match info, lineups, H2H, form, stats) in the match overlay
|
|
|
|
| 3 |
|
| 4 |
(function(){
|
| 5 |
if(window._mdLoaded) return;
|
|
|
|
| 12 |
s.textContent=`
|
| 13 |
.md-sec{margin-bottom:14px}
|
| 14 |
.md-sec-title{font-size:13px;font-weight:800;color:#5cb87a;margin-bottom:6px;padding-bottom:4px;border-bottom:1px solid #2a2a2a;display:flex;align-items:center;gap:6px}
|
| 15 |
+
.md-pre-match{background:linear-gradient(135deg,#1a2a1f,#0d1117);border:1px solid #2d8659;border-radius:10px;padding:12px;text-align:center;margin-bottom:12px}
|
| 16 |
+
.md-pre-league{font-size:9px;color:#5cb87a;font-weight:700;text-transform:uppercase;letter-spacing:1px;margin-bottom:6px}
|
| 17 |
+
.md-pre-teams{display:flex;align-items:center;justify-content:center;gap:12px}
|
| 18 |
+
.md-pre-team{display:flex;flex-direction:column;align-items:center;gap:4px;flex:1}
|
| 19 |
+
.md-pre-team img{width:32px;height:32px;object-fit:contain}
|
| 20 |
+
.md-pre-team span{font-size:11px;color:#ddd;text-align:center}
|
| 21 |
+
.md-pre-vs{font-size:18px;font-weight:900;color:#f0c040;min-width:40px;text-align:center}
|
| 22 |
+
.md-pre-info{display:flex;gap:12px;justify-content:center;margin-top:10px;flex-wrap:wrap}
|
| 23 |
+
.md-pre-info-item{font-size:10px;color:#aaa;display:flex;align-items:center;gap:3px}
|
| 24 |
+
.md-pre-info-item b{color:#ddd;font-size:11px}
|
| 25 |
.md-preview-text{font-size:12px;color:#ccc;line-height:1.6;background:#1a1a1a;border-radius:8px;padding:10px;border-left:3px solid #2d8659;max-height:300px;overflow-y:auto}
|
| 26 |
.md-lineups{display:grid;grid-template-columns:1fr 1fr;gap:10px}
|
| 27 |
.md-team-box{background:#1a2a1f;border:1px solid #2a3a2a;border-radius:8px;padding:8px}
|
|
|
|
| 29 |
.md-formation{font-size:9px;color:#888;text-align:center;margin-bottom:6px}
|
| 30 |
.md-player-item{font-size:10px;color:#ccc;padding:2px 0;border-bottom:1px solid #1a2a1f}
|
| 31 |
.md-h2h-item{display:flex;align-items:center;gap:6px;padding:6px;background:#1a1a1a;border-radius:6px;margin-bottom:3px;font-size:11px}
|
| 32 |
+
.md-h2h-date{font-size:9px;color:#888;min-width:55px;flex-shrink:0}
|
| 33 |
+
.md-h2h-league{font-size:8px;color:#666}
|
| 34 |
+
.md-h2h-teams{flex:1;display:flex;align-items:center;gap:4px;min-width:0}
|
| 35 |
+
.md-h2h-home{text-align:right;flex:1;color:#ddd;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
| 36 |
+
.md-h2h-away{text-align:left;flex:1;color:#ddd;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
| 37 |
+
.md-h2h-score{font-size:11px;font-weight:800;color:#f0c040;min-width:36px;text-align:center;flex-shrink:0}
|
| 38 |
+
.md-h2h-stats{display:flex;flex-direction:column;gap:4px}
|
| 39 |
+
.md-h2h-stat-row{display:flex;align-items:center;gap:8px;font-size:10px}
|
| 40 |
+
.md-h2h-stat-home{width:30px;text-align:right;color:#5cb87a;font-weight:700;flex-shrink:0}
|
| 41 |
+
.md-h2h-stat-label{flex:1;text-align:center;color:#888;font-size:9px}
|
| 42 |
+
.md-h2h-stat-away{width:30px;text-align:left;color:#e85d04;font-weight:700;flex-shrink:0}
|
| 43 |
+
.md-form-item{display:flex;align-items:center;gap:6px;padding:5px 6px;background:#1a1a1a;border-radius:6px;margin-bottom:2px;font-size:10px}
|
| 44 |
+
.md-form-result{padding:1px 5px;border-radius:3px;font-size:8px;font-weight:800;color:#fff;flex-shrink:0}
|
| 45 |
+
.md-form-result.T{background:#2d8659}
|
| 46 |
+
.md-form-result.B{background:#c0392b}
|
| 47 |
+
.md-form-result.H{background:#666}
|
| 48 |
+
.md-form-date{font-size:9px;color:#888;min-width:50px;flex-shrink:0}
|
| 49 |
+
.md-form-teams{flex:1;display:flex;align-items:center;gap:4px;min-width:0}
|
| 50 |
+
.md-form-home{text-align:right;flex:1;color:#ddd;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
| 51 |
+
.md-form-away{text-align:left;flex:1;color:#ddd;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
| 52 |
+
.md-form-score{font-size:10px;font-weight:700;color:#f0c040;min-width:30px;text-align:center;flex-shrink:0}
|
| 53 |
+
.md-form-section{margin-bottom:10px}
|
| 54 |
+
.md-form-team-label{font-size:11px;font-weight:700;color:#aaa;margin-bottom:4px}
|
| 55 |
.md-no-data{color:#777;font-size:12px;padding:16px;text-align:center}
|
| 56 |
.md-err{color:#e74c3c;font-size:12px;padding:16px;text-align:center}
|
| 57 |
.mo-tab-detail{}
|
|
|
|
| 61 |
|
| 62 |
function esc(s){return String(s||'').replace(/[&<>"']/g,function(m){return{'&':'&','<':'<','>':'>','"':'"',"'":'''}[m]})}
|
| 63 |
|
| 64 |
+
// === 1. Override openMatch to always set _currentEventId ===
|
| 65 |
const _origOpenMatch = window.openMatch;
|
| 66 |
window.openMatch = function(id){
|
| 67 |
if(id) window._currentEventId = String(id);
|
| 68 |
if(_origOpenMatch) _origOpenMatch.call(this, id);
|
|
|
|
| 69 |
setTimeout(function(){
|
| 70 |
injectDetailTab();
|
| 71 |
loadMatchTab('detail');
|
|
|
|
| 79 |
if(_origLoadMatchTab) _origLoadMatchTab.call(this, tab);
|
| 80 |
return;
|
| 81 |
}
|
|
|
|
|
|
|
| 82 |
document.querySelectorAll('.mo-tab').forEach(function(t){ t.classList.remove('active'); });
|
| 83 |
document.querySelectorAll('.mo-tab').forEach(function(t){
|
| 84 |
const txt = t.textContent || '';
|
| 85 |
if(txt.includes('Chi tiết') || txt.includes('📋')) t.classList.add('active');
|
| 86 |
});
|
|
|
|
| 87 |
const el = document.getElementById('mo-body');
|
| 88 |
if(!el) return;
|
| 89 |
el.innerHTML = '<div class="md-no-data">⏳ Đang tải chi tiết trận đấu...</div>';
|
|
|
|
| 90 |
const eventId = window._currentEventId;
|
| 91 |
if(!eventId){
|
| 92 |
+
el.innerHTML = '<div class="md-err">⚠️ Không tìm thấy mã trận đấu.</div>';
|
| 93 |
return;
|
| 94 |
}
|
|
|
|
| 95 |
try{
|
| 96 |
const r = await fetch('/api/match/' + eventId + '/detail');
|
| 97 |
if(!r.ok) throw new Error('API error ' + r.status);
|
|
|
|
| 107 |
function renderMatchDetail(el, data){
|
| 108 |
let h = '';
|
| 109 |
|
| 110 |
+
// 0. Pre-match info card
|
| 111 |
+
const info = data.info || {};
|
| 112 |
+
if(info.home_team && info.away_team){
|
| 113 |
+
h += '<div class="md-pre-match">';
|
| 114 |
+
if(info.league) h += '<div class="md-pre-league">'+esc(info.league)+'</div>';
|
| 115 |
+
h += '<div class="md-pre-teams">';
|
| 116 |
+
h += '<div class="md-pre-team">';
|
| 117 |
+
if(info.home_logo) h += '<img src="'+esc(info.home_logo)+'" alt="">';
|
| 118 |
+
h += '<span>'+esc(info.home_team)+'</span></div>';
|
| 119 |
+
h += '<div class="md-pre-vs">VS</div>';
|
| 120 |
+
h += '<div class="md-pre-team">';
|
| 121 |
+
if(info.away_logo) h += '<img src="'+esc(info.away_logo)+'" alt="">';
|
| 122 |
+
h += '<span>'+esc(info.away_team)+'</span></div>';
|
| 123 |
+
h += '</div>';
|
| 124 |
+
if(info.date || info.time || info.stadium || info.referee){
|
| 125 |
+
h += '<div class="md-pre-info">';
|
| 126 |
+
if(info.date) h += '<span class="md-pre-info-item">📅 <b>'+esc(info.date)+'</b></span>';
|
| 127 |
+
if(info.time) h += '<span class="md-pre-info-item">🕐 <b>'+esc(info.time)+'</b></span>';
|
| 128 |
+
if(info.stadium) h += '<span class="md-pre-info-item">🏟 <b>'+esc(info.stadium)+'</b></span>';
|
| 129 |
+
if(info.referee) h += '<span class="md-pre-info-item">👨⚖️ <b>'+esc(info.referee)+'</b></span>';
|
| 130 |
+
h += '</div>';
|
| 131 |
+
}
|
| 132 |
+
h += '</div>';
|
| 133 |
+
} else if(data.pre_match_html){
|
| 134 |
+
let clean = data.pre_match_html
|
| 135 |
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
|
| 136 |
.replace(/<iframe[^>]*>[\s\S]*?<\/iframe>/gi, '')
|
| 137 |
.replace(/<ins[^>]*>[\s\S]*?<\/ins>/gi, '');
|
|
|
|
|
|
|
| 138 |
h += '<div class="md-sec"><div class="md-sec-title">📋 Thông tin trận đấu</div>';
|
| 139 |
+
h += '<div class="md-preview-text">' + clean + '</div></div>';
|
| 140 |
}
|
| 141 |
|
| 142 |
+
// 1. H2H Stats comparison
|
| 143 |
+
if(data.h2h_stats_parsed && Object.keys(data.h2h_stats_parsed).length > 0){
|
| 144 |
+
h += '<div class="md-sec"><div class="md-sec-title">📊 Thống kê đối đầu</div>';
|
| 145 |
+
h += '<div class="md-h2h-stats">';
|
| 146 |
+
const statLabels = data.h2h_stats_parsed;
|
| 147 |
+
for(const label in statLabels){
|
| 148 |
+
const s = statLabels[label];
|
| 149 |
+
h += '<div class="md-h2h-stat-row">';
|
| 150 |
+
h += '<span class="md-h2h-stat-home">'+esc(s.home)+'</span>';
|
| 151 |
+
h += '<span class="md-h2h-stat-label">'+esc(label)+'</span>';
|
| 152 |
+
h += '<span class="md-h2h-stat-away">'+esc(s.away)+'</span>';
|
| 153 |
+
h += '</div>';
|
| 154 |
+
}
|
| 155 |
+
h += '</div></div>';
|
| 156 |
+
} else if(data.h2h_stats_html && data.h2h_stats_html.length > 10){
|
| 157 |
+
h += '<div class="md-sec"><div class="md-sec-title">📊 Thống kê đối đầu</div>';
|
| 158 |
+
h += '<div>' + data.h2h_stats_html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,'').replace(/<iframe[^>]*>[\s\S]*?<\/iframe>/gi,'') + '</div></div>';
|
| 159 |
}
|
| 160 |
|
| 161 |
+
// 2. H2H matches
|
| 162 |
+
if(data.h2h && data.h2h.length > 0){
|
| 163 |
+
h += '<div class="md-sec"><div class="md-sec-title">🔄 Lịch sử đối đầu</div>';
|
| 164 |
+
const h2hList = data.h2h.slice(0, 10);
|
| 165 |
+
h2hList.forEach(function(m){
|
| 166 |
+
h += '<div class="md-h2h-item">';
|
| 167 |
+
h += '<span class="md-h2h-date">'+esc(m.date||'')+'</span>';
|
| 168 |
+
if(m.league) h += '<span class="md-h2h-league">'+esc(m.league)+'</span>';
|
| 169 |
+
h += '<span class="md-h2h-teams">';
|
| 170 |
+
h += '<span class="md-h2h-home">'+esc(m.home||'')+'</span>';
|
| 171 |
+
h += '<span class="md-h2h-score">'+esc(m.score||'vs')+'</span>';
|
| 172 |
+
h += '<span class="md-h2h-away">'+esc(m.away||'')+'</span>';
|
| 173 |
+
h += '</span></div>';
|
| 174 |
+
});
|
| 175 |
+
h += '</div>';
|
| 176 |
+
} else if(data.h2h_html && data.h2h_html.length > 10){
|
| 177 |
+
h += '<div class="md-sec"><div class="md-sec-title">🔄 Lịch sử đối đầu</div>';
|
| 178 |
h += '<div>' + data.h2h_html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,'').replace(/<iframe[^>]*>[\s\S]*?<\/iframe>/gi,'') + '</div></div>';
|
|
|
|
|
|
|
|
|
|
| 179 |
}
|
| 180 |
|
| 181 |
+
// 3. Team form
|
| 182 |
+
if((data.home_form && data.home_form.length > 0) || (data.away_form && data.away_form.length > 0)){
|
| 183 |
+
h += '<div class="md-sec"><div class="md-sec-title">📈 Phong độ gần đây</div>';
|
| 184 |
+
if(data.home_form && data.home_form.length > 0){
|
| 185 |
+
h += '<div class="md-form-section">';
|
| 186 |
+
h += '<div class="md-form-team-label">🏠 Đội nhà</div>';
|
| 187 |
+
data.home_form.slice(0, 5).forEach(function(m){ h += renderFormItem(m); });
|
| 188 |
+
h += '</div>';
|
| 189 |
+
}
|
| 190 |
+
if(data.away_form && data.away_form.length > 0){
|
| 191 |
+
h += '<div class="md-form-section">';
|
| 192 |
+
h += '<div class="md-form-team-label">✈️ Đội khách</div>';
|
| 193 |
+
data.away_form.slice(0, 5).forEach(function(m){ h += renderFormItem(m); });
|
| 194 |
+
h += '</div>';
|
| 195 |
+
}
|
| 196 |
+
h += '</div>';
|
| 197 |
}
|
| 198 |
|
| 199 |
+
// 4. Player performance stats
|
| 200 |
+
if(data.stats_html && data.stats_html.length > 10){
|
| 201 |
+
h += '<div class="md-sec"><div class="md-sec-title">🌟 Thông số cầu thủ</div>';
|
| 202 |
+
h += '<div>' + data.stats_html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi,'').replace(/<iframe[^>]*>[\s\S]*?<\/iframe>/gi,'') + '</div></div>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
}
|
| 204 |
|
| 205 |
if(!h){
|
| 206 |
+
h = '<div class="md-no-data">⏳ Chưa có chi tiết cho trận đấu này.<br><small style="color:#666">Dữ liệu sẽ cập nhật khi giải khởi tranh hoặc trận đấu bắt đầu.</small></div>';
|
| 207 |
}
|
|
|
|
| 208 |
el.innerHTML = h;
|
|
|
|
| 209 |
el.querySelectorAll('a').forEach(function(a){ a.addEventListener('click', function(e){ e.preventDefault(); }); });
|
| 210 |
}
|
| 211 |
|
| 212 |
+
function renderFormItem(m){
|
| 213 |
+
let h = '<div class="md-form-item">';
|
| 214 |
+
if(m.result) h += '<span class="md-form-result '+esc(m.result)+'">'+esc(m.result)+'</span>';
|
| 215 |
+
h += '<span class="md-form-date">'+esc(m.date||'')+'</span>';
|
| 216 |
+
h += '<span class="md-form-teams">';
|
| 217 |
+
h += '<span class="md-form-home">'+esc(m.home||'')+'</span>';
|
| 218 |
+
h += '<span class="md-form-score">'+esc(m.score||'')+'</span>';
|
| 219 |
+
h += '<span class="md-form-away">'+esc(m.away||'')+'</span>';
|
| 220 |
+
h += '</span></div>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
return h;
|
| 222 |
}
|
| 223 |
|
| 224 |
+
// === 4. Inject "Chi tiết" tab ===
|
| 225 |
function injectDetailTab(){
|
| 226 |
const tabs = document.querySelector('.mo-tabs');
|
| 227 |
if(!tabs || document.querySelector('.mo-tab-detail')) return;
|
|
|
|
| 232 |
tabs.insertBefore(d, tabs.firstChild);
|
| 233 |
}
|
| 234 |
|
| 235 |
+
// === 5. Intercept clicks to capture event_id ===
|
| 236 |
document.addEventListener('click', function(e){
|
| 237 |
const md = e.target.closest('.match-detail');
|
| 238 |
if(!md) return;
|
|
|
|
| 244 |
}
|
| 245 |
}, true);
|
| 246 |
|
|
|
|
| 247 |
if(document.readyState==='loading') document.addEventListener('DOMContentLoaded', function(){ setTimeout(injectDetailTab, 1000); });
|
| 248 |
else setTimeout(injectDetailTab, 1000);
|
| 249 |
})();
|