您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays shots on target below match results
// ==UserScript== // @name MZ - SoT // @namespace douglaskampl // @version 1.1 // @description Displays shots on target below match results // @author Douglas // @match https://www.managerzone.com/?p=match&sub=played // @match https://www.managerzone.com/?p=league* // @match https://www.managerzone.com/?p=friendlyseries* // @match https://www.managerzone.com/?p=cup* // @match https://www.managerzone.com/?p=private_cup* // @match https://www.managerzone.com/?p=national_teams* // @grant GM_addStyle // @run-at document-idle // @license MIT // ==/UserScript== (function () { 'use strict'; GM_addStyle(`.sot-container-dk { display: block; margin: 2px auto 0 auto; font-size: 0.9em; font-weight: bold; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; opacity: 0; transform: translateY(10px); transition: opacity 0.5s ease-out, transform 0.5s ease-out; color: navy; line-height: 1; text-align: center; } .sot-container-dk.visible { opacity: 1; transform: translateY(0); } .sot-spinner-dk { display: inline-block; width: 10px; height: 10px; margin-right: 6px; vertical-align: -1px; border: 2px solid rgba(0, 0, 0, 0.1); border-radius: 50%; border-top-color: #555; animation: spin 1s ease-in-out infinite; } .sot-fetching-dk { color: #888; } .sot-loaded-dk { color: #333; } .sot-error-dk { color: #D32F2F; } @keyframes spin { to { transform: rotate(360deg); } }`); const fetchAndDisplaySoT = (mid) => { const resultUrl = `/?p=match&sub=result&mid=${mid}`; fetch(resultUrl) .then(response => { if (!response.ok) throw new Error(`Network response not OK. Status: ${response.status}`); return response.text(); }) .then(html => { const doc = new DOMParser().parseFromString(html, "text/html"); let statsTable = null; const candidateTables = doc.querySelectorAll('table.statsLite.marker'); for (const table of candidateTables) { const headerCells = table.querySelectorAll('thead tr:first-child td'); const statsTableFound = headerCells && headerCells.length === 3; if (statsTableFound) { statsTable = table; break; } } if (!statsTable) { throw new Error("Could not find the stats table."); } const sotRow = statsTable.querySelector('tbody tr:nth-child(8)'); const sotContainer = document.getElementById(`sot-container-${mid}`); if (!sotContainer) { return; } if (sotRow) { const cells = sotRow.querySelectorAll('td'); if (cells.length === 3) { const homeSoT = cells[1].textContent.trim(); const awaySoT = cells[2].textContent.trim(); sotContainer.innerHTML = `${homeSoT} - ${awaySoT}`; sotContainer.className = 'sot-container-dk sot-loaded-dk visible'; } else { throw new Error(`The 8th row was found, but it has ${cells.length} cells instead of the expected 3.`); } } else { throw new Error("Found the correct stats table, but could not find the 8th row (tr:nth-child(8)) within it."); } }) .catch(error => { const sotContainer = document.getElementById(`sot-container-${mid}`); if(sotContainer) { sotContainer.textContent = 'Error'; sotContainer.className = 'sot-container-dk sot-error-dk visible'; } }); }; const processPlayedMatchesPage = () => { const matchElements = document.querySelectorAll('#fixtures-results-list > dd.odd, #fixtures-results-list > dd.even'); matchElements.forEach(matchElement => { if (matchElement.querySelector('.score-cell-wrapper') && !matchElement.querySelector('.sot-container-dk')) { const anyMatchLink = matchElement.querySelector('a[href*="&mid="]'); if (!anyMatchLink) return; const match = anyMatchLink.href.match(/mid=(\d+)/); const mid = match && match[1] ? match[1] : null; if (mid) { const scoreWrapper = matchElement.querySelector('.score-cell-wrapper'); const sotContainer = document.createElement('div'); sotContainer.id = `sot-container-${mid}`; sotContainer.className = 'sot-container-dk sot-fetching-dk'; sotContainer.innerHTML = `<div class="sot-spinner-dk"></div>SoT`; scoreWrapper.appendChild(sotContainer); setTimeout(() => sotContainer.classList.add('visible'), 10); fetchAndDisplaySoT(mid); } } }); }; const processHitlistTables = () => { const tables = document.querySelectorAll('table.hitlist.marker'); const scoreRegex = /^\d+\s*-\s*\d+$/; tables.forEach(table => { const rows = table.querySelectorAll('tbody tr'); rows.forEach(row => { if (row.dataset.sotProcessed) return; const scoreCell = row.querySelector('td:nth-child(2)'); const scoreLink = scoreCell?.querySelector('a[href*="mid="]'); if (!scoreCell || !scoreLink) return; if (!scoreRegex.test(scoreLink.textContent.trim())) return; row.dataset.sotProcessed = 'true'; const midMatch = scoreLink.href.match(/mid=(\d+)/); const mid = midMatch?.[1]; if (!mid) return; const sotContainer = document.createElement('div'); sotContainer.id = `sot-container-${mid}`; sotContainer.className = 'sot-container-dk sot-fetching-dk'; sotContainer.innerHTML = `<div class="sot-spinner-dk"></div>SoT`; scoreCell.style.textAlign = 'center'; scoreCell.style.lineHeight = '1.4'; scoreCell.appendChild(sotContainer); setTimeout(() => sotContainer.classList.add('visible'), 10); fetchAndDisplaySoT(mid); }); }); }; const routeByPage = () => { const params = new URLSearchParams(window.location.search); const page = params.get('p'); const sub = params.get('sub'); if (page === 'match' && sub === 'played') { processPlayedMatchesPage(); } else if (['league', 'friendlyseries', 'cup', 'private_cup', 'national_teams'].includes(page)) { processHitlistTables(); } else { } }; let processTimeout; const observer = new MutationObserver(() => { clearTimeout(processTimeout); processTimeout = setTimeout(() => { routeByPage(); }, 500); }); routeByPage(); observer.observe(document.body, { childList: true, subtree: true }); })();