1(function () { 2 'use strict'; 3 4 var REFRESH_INTERVAL_MS = 60000; // cada cuánto se piden datos frescos en segundo plano 5 6 function initTabs(root) { 7 root.querySelectorAll('.fp-tab-btn').forEach(function (btn) { 8 btn.addEventListener('click', function () { 9 root.dataset.userTab = btn.dataset.target; // recordar la pestaña elegida por el usuario 10 root.querySelectorAll('.fp-tab-btn').forEach(function (b) { b.classList.remove('active'); }); 11 root.querySelectorAll('.fp-slider-rel').forEach(function (s) { s.classList.remove('active'); }); 12 btn.classList.add('active'); 13 var panel = root.querySelector('.fp-slider-rel[data-tab="' + btn.dataset.target + '"]'); 14 if (panel) panel.classList.add('active'); 15 }); 16 }); 17 } 18 19 function initNav(root) { 20 root.querySelectorAll('.fp-next').forEach(function (btn) { 21 btn.addEventListener('click', function () { 22 btn.parentElement.querySelector('.fp-scroll-row').scrollBy({ left: 280, behavior: 'smooth' }); 23 }); 24 }); 25 root.querySelectorAll('.fp-prev').forEach(function (btn) { 26 btn.addEventListener('click', function () { 27 btn.parentElement.querySelector('.fp-scroll-row').scrollBy({ left: -280, behavior: 'smooth' }); 28 }); 29 }); 30 } 31 32 function initLigasPanel(root) { 33 var ligasBtn = root.querySelector('.fp-ligas-btn'); 34 var ligasPanel = root.querySelector('.fp-ligas-panel'); 35 if (!ligasBtn) return; 36 37 ligasBtn.addEventListener('click', function () { 38 ligasPanel.classList.toggle('open'); 39 }); 40 document.addEventListener('click', function (e) { 41 if (!root.querySelector('.fp-ligas-wrap').contains(e.target)) { 42 ligasPanel.classList.remove('open'); 43 } 44 }); 45 } 46 47 // Mensaje "no hay partidos de esta liga" para las filas normales 48 // (pestañas Hoy/Mañana). En la agenda no se usa por fila/dÃa, porque el 49 // bloque del dÃa entero se oculta cuando no tiene partidos de la liga 50 // elegida (ver showAgendaEmptyMessage más abajo, que cubre el caso de 51 // que TODOS los dÃas queden ocultos). 52 function showEmptyMessage(row, code) { 53 var visibles = row.querySelectorAll('.fp-card:not([style*="display: none"])'); 54 var empty = row.querySelector('.fp-empty-filtered'); 55 if (code && visibles.length === 0) { 56 if (!empty) { 57 empty = document.createElement('p'); 58 empty.className = 'fp-empty fp-empty-filtered'; 59 empty.textContent = 'No hay partidos de esta liga.'; 60 row.appendChild(empty); 61 } 62 } else if (empty) { 63 empty.remove(); 64 } 65 } 66 67 // Si, tras filtrar por liga, ningún dÃa de la agenda tiene partidos 68 // visibles, se muestra un único aviso a nivel de agenda completa (en 69 // vez de dejar el bloque en blanco sin explicación). 70 function showAgendaEmptyMessage(root, code) { 71 var body = root.querySelector('.fp-agenda-body'); 72 if (!body) return; 73 var diasVisibles = body.querySelectorAll('.fp-agenda-day:not([style*="display: none"])'); 74 var empty = body.querySelector('.fp-empty-filtered'); 75 if (code && diasVisibles.length === 0) { 76 if (!empty) { 77 empty = document.createElement('p'); 78 empty.className = 'fp-empty fp-empty-filtered'; 79 empty.textContent = 'No hay partidos de esta liga en los próximos dÃas.'; 80 body.appendChild(empty); 81 } 82 } else if (empty) { 83 empty.remove(); 84 } 85 } 86 87 // Aplica el filtro de liga actual (por código) a las tarjetas ya 88 // presentes en el DOM. Se usa tanto al hacer clic en una liga como 89 // después de cada auto-refresh, para no perder el filtro elegido. 90 // Funciona igual en las pestañas Hoy/Mañana (.fp-scroll-row) que en la 91 // agenda de página completa agrupada por dÃa (.fp-list-row). 92 function applyLigaFilter(root, code) { 93 root.querySelectorAll('.fp-card, .fp-list-row').forEach(function (card) { 94 var match = !code || card.dataset.liga === code; 95 card.style.display = match ? '' : 'none'; 96 }); 97 98 // Los placeholders se ocultan al filtrar para no dejar huecos de 99 // "faltan partidos" cuando en realidad hay más partidos fuera de
100 // la liga seleccionada. 101 root.querySelectorAll('.fp-card-placeholder').forEach(function (ph) { 102 ph.style.display = code ? 'none' : ''; 103 }); 104 105 root.querySelectorAll('.fp-scroll-row').forEach(function (row) { 106 showEmptyMessage(row, code); 107 }); 108 109 // En la agenda, si un dÃa se queda sin partidos tras filtrar, se 110 // oculta el bloque completo de ese dÃa (encabezado incluido). 111 root.querySelectorAll('.fp-agenda-day').forEach(function (day) { 112 var visibles = day.querySelectorAll('.fp-list-row:not([style*="display: none"])'); 113 day.style.display = (code && visibles.length === 0) ? 'none' : ''; 114 }); 115 116 if (root.dataset.agenda) { 117 showAgendaEmptyMessage(root, code); 118 } 119 } 120 121 function initLigaFilter(root) { 122 var ligasBtn = root.querySelector('.fp-ligas-btn'); 123 var ligasPanel = root.querySelector('.fp-ligas-panel'); 124 125 root.querySelectorAll('.fp-liga-opt').forEach(function (opt) { 126 opt.addEventListener('click', function (e) { 127 e.preventDefault(); 128 var code = opt.dataset.code; 129 130 root.querySelectorAll('.fp-liga-opt').forEach(function (o) { o.classList.remove('active'); }); 131 opt.classList.add('active'); 132 root.dataset.ligaCode = code; // recordar el filtro elegido por el usuario 133 134 applyLigaFilter(root, code); 135 136 ligasBtn.innerHTML = (code ? opt.textContent : 'Ligas') + ' <span>â</span>'; 137 if (ligasPanel) ligasPanel.classList.remove('open'); 138 }); 139 }); 140 } 141 142 // Pide los partidos de Hoy/Mañana frescos al servidor. En la primera 143 // carga (isInitial) usa la pestaña que la API recomienda por defecto. En 144 // los refrescos automáticos posteriores respeta la pestaña y el filtro 145 // de liga que el usuario ya haya elegido, para no interrumpirlo. 146 function loadMatches(root, isInitial) { 147 if (typeof fpTabsData === 'undefined') return; 148 149 var url = fpTabsData.ajaxUrl 150 + '?action=fp_get_matches' 151 + '&nonce=' + encodeURIComponent(fpTabsData.nonce) 152 + '&_=' + Date.now(); // evita que la propia URL se quede cacheada 153 154 fetch(url, { credentials: 'same-origin', cache: 'no-store' }) 155 .then(function (res) { return res.json(); }) 156 .then(function (json) { 157 if (!json || !json.success) return; 158 var data = json.data; 159 160 var hoyBtn = root.querySelector('.fp-tab-btn[data-target="hoy"] span'); 161 var mananaBtn = root.querySelector('.fp-tab-btn[data-target="manana"] span'); 162 if (hoyBtn) hoyBtn.textContent = data.hoyLabel; 163 if (mananaBtn) mananaBtn.textContent = data.mananaLabel; 164 165 var hoyRow = root.querySelector('.fp-slider-rel[data-tab="hoy"] .fp-scroll-row'); 166 var mananaRow = root.querySelector('.fp-slider-rel[data-tab="manana"] .fp-scroll-row'); 167 if (hoyRow) hoyRow.innerHTML = data.hoyHtml; 168 if (mananaRow) mananaRow.innerHTML = data.mananaHtml; 169 170 var targetTab = isInitial ? data.defaultTab : (root.dataset.userTab || data.defaultTab); 171 root.querySelectorAll('.fp-tab-btn').forEach(function (b) { b.classList.remove('active'); }); 172 root.querySelectorAll('.fp-slider-rel').forEach(function (s) { s.classList.remove('active'); }); 173 var activeBtn = root.querySelector('.fp-tab-btn[data-target="' + targetTab + '"]'); 174 var activePanel = root.querySelector('.fp-slider-rel[data-tab="' + targetTab + '"]'); 175 if (activeBtn) activeBtn.classList.add('active'); 176 if (activePanel) activePanel.classList.add('active'); 177 178 var ligaCode = root.dataset.ligaCode || ''; 179 if (ligaCode) applyLigaFilter(root, ligaCode); 180 }) 181 .catch(function () { /* si falla, se conserva el contenido que ya habÃa en pantalla */ }); 182 } 183 184 // Pide la agenda completa (varios dÃas agrupados) fresca al servidor y 185 // reemplaza el cuerpo entero, reaplicando el filtro de liga si habÃa uno. 186 function loadAgenda(root) { 187 if (typeof fpTabsData === 'undefined') return; 188 189 var dias = root.dataset.dias || ''; 190 var url = fpTabsData.ajaxUrl 191 + '?action=fp_get_agenda' 192 + '&nonce=' + encodeURIComponent(fpTabsData.nonce) 193 + (dias ? '&dias=' + encodeURIComponent(dias) : '') 194 + '&_=' + Date.now(); 195 196 fetch(url, { credentials: 'same-origin', cache: 'no-store' }) 197 .then(function (res) { return res.json(); }) 198 .then(function (json) { 199 if (!json || !json.success) return; 200 var body = root.querySelector('.fp-agenda-body'); 201 if (body) body.innerHTML = json.data.html; 202 203 var ligaCode = root.dataset.ligaCode || ''; 204 if (ligaCode) applyLigaFilter(root, ligaCode); 205 }) 206 .catch(function () { /* si falla, se conserva el contenido que ya habÃa en pantalla */ }); 207 } 208 209 function initAutoRefresh(root, loader) { 210 setInterval(function () { 211 // No pedimos datos si la pestaña del navegador está en segundo 212 // plano, para no gastar cuota de la API sin que nadie lo vea. 213 if (document.hidden) return; 214 loader(root, false); 215 }, REFRESH_INTERVAL_MS); 216 } 217 218 function initInstance(root) { 219 initNav(root); 220 initLigasPanel(root); 221 initLigaFilter(root); 222 223 if (root.dataset.agenda) { 224 loadAgenda(root); 225 initAutoRefresh(root, loadAgenda); 226 } else { 227 initTabs(root); 228 loadMatches(root, true); 229 initAutoRefresh(root, loadMatches); 230 } 231 } 232 233 document.addEventListener('DOMContentLoaded', function () { 234 document.querySelectorAll('.fp-main-container').forEach(initInstance); 235 }); 236})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.