您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays leagues and world leagues, grouped by div and/or region, in a single view
当前为
// ==UserScript== // @name MZ - Multiple League Standings in a Single View // @namespace douglaskampl // @version 3.6 // @description Displays leagues and world leagues, grouped by div and/or region, in a single view // @author Douglas // @match https://www.managerzone.com/?p=team // @icon https://www.google.com/s2/favicons?sz=64&domain=managerzone.com // @grant GM_addStyle // @grant GM_getResourceText // @resource sLeagueStandingsStyles https://u18mz.vercel.app/mz/userscript/other/sLeagueStandings.css // @run-at document-idle // @license MIT // ==/UserScript== (function () { "use strict"; GM_addStyle(GM_getResourceText("sLeagueStandingsStyles")); const UI = { TEXTS: { TOGGLE_UP: "UP 上", TOGGLE_DOWN: "DOWN 下", LOADING: "Loading ロード中…" }, SELECTORS: { TEAM_INFO: "#infoAboutTeam", STADIUM_WRAPPER: "#team-stadium-wrapper", SHORTCUT_LINK: "#shortcut_link_thezone" } }; const LEAGUE_TYPES = { SENIOR: "senior", U18: "u18", U21: "u21", U23: "u23", WORLD: "world", U18_WORLD: "u18_world", U21_WORLD: "u21_world", U23_WORLD: "u23_world" }; const DIVISION = { NAMES: { TOP: "Top Division", TOP_SERIES: "Top Series" }, STRUCTURE: { BASE_DIVISIONS: 3, MAX_LEVEL: 4 } }; const REGIONS = { SOCCER: { COUNTRIES: [ { name: "Argentina", start: 16096 }, { name: "Brazil", start: 26187 }, { name: "China", start: 70847 }, { name: "Germany", start: 12086 }, { name: "Italy", start: 10625 }, { name: "Netherlands", start: 15004 }, { name: "Portugal", start: 17566 }, { name: "Spain", start: 10746 }, { name: "Poland", start: 13181 }, { name: "Romania", start: 17929 }, { name: "Sweden", start: 43 }, { name: "Turkey", start: 20356 } ], UXX_REGIONS: [ { name: "Argentina", start: 1 }, { name: "Brazil", start: 122 }, { name: "Latin America, USA and Canada", start: 727 }, { name: "Central Europe", start: 848 }, { name: "Iberia", start: 969 }, { name: "Mediterranean", start: 1090 }, { name: "Northern Europe", start: 1211 }, { name: "Poland", start: 243 }, { name: "Romania", start: 364 }, { name: "Sweden", start: 485 }, { name: "Turkey", start: 606 }, { name: "China/Asia/Africa", start: 1332 } ] }, HOCKEY: { COUNTRIES: [ { name: "Brazil", start: 7900 }, { name: "Sweden", start: 1 }, { name: "Argentina", start: 2 }, { name: "Poland", start: 23 }, { name: "Portugal", start: 24 }, { name: "Spain", start: 12 }, { name: "Romania", start: 25 }, { name: "Turkey", start: 27 }, { name: "China", start: 13727 } ], UXX_REGIONS: [ { name: "Northern Europe", start: 1 }, { name: "Southern Europe", start: 122 }, { name: "Rest of the World", start: 243 } ] } }; const CONSTANTS = { BUTTON_NAMES: [ "Senior Leagues", "U18 Leagues", "U21 Leagues", "U23 Leagues", "Senior World Leagues", "U18 World Leagues", "U21 World Leagues", "U23 World Leagues" ], TOGGLE_TEXT_DOWN: UI.TEXTS.TOGGLE_DOWN, TOGGLE_TEXT_UP: UI.TEXTS.TOGGLE_UP, LOADING_TEXT: UI.TEXTS.LOADING }; class LeagueManager { constructor() { const shortcutLink = document.querySelector(UI.SELECTORS.SHORTCUT_LINK); this.sport = new URL(shortcutLink.href).searchParams.get("sport"); const teamInfo = document.querySelector(UI.SELECTORS.TEAM_INFO); this.teamId = RegExp(/\((\d+)\)/).exec(teamInfo.querySelector("dd").textContent)[1]; this.seniorLeagues = this.getSeniorLeagues(); this.worldLeagues = { World: this.getWorldLeaguesObj() }; this.uxxLeagues = this.getUxxLeagues(); } getSeniorLeagues() { const countries = this.sport === "soccer" ? REGIONS.SOCCER.COUNTRIES : REGIONS.HOCKEY.COUNTRIES; return countries.reduce((acc, { name, start }) => { acc[name] = { [DIVISION.NAMES.TOP]: [start] }; return acc; }, {}); } getWorldLeaguesObj() { const leagues = {}; let start = 1; for (let i = 0; i <= DIVISION.STRUCTURE.MAX_LEVEL; i++) { const divisionName = i === 0 ? DIVISION.NAMES.TOP_SERIES : `Division ${i}`; leagues[divisionName] = []; const numLeagues = Math.pow(DIVISION.STRUCTURE.BASE_DIVISIONS, i); for (let j = 0; j < numLeagues; j++) { leagues[divisionName].push(start++); } } return leagues; } getUxxLeagues() { const regions = this.sport === "soccer" ? REGIONS.SOCCER.UXX_REGIONS : REGIONS.HOCKEY.UXX_REGIONS; const obj = {}; regions.forEach(region => { obj[region.name] = { [DIVISION.NAMES.TOP]: [region.start], "Division 1": Array.from({ length: DIVISION.STRUCTURE.BASE_DIVISIONS }, (_, i) => region.start + i + 1), "Division 2": Array.from( { length: Math.pow(DIVISION.STRUCTURE.BASE_DIVISIONS, 2) }, (_, i) => region.start + i + 4 ) }; }); return obj; } getAllLeagues(leaguesObj) { const allLeagues = {}; Object.entries(leaguesObj).forEach(([country, leagues]) => { Object.entries(leagues).forEach(([leagueName, ids]) => { if (!allLeagues[leagueName]) allLeagues[leagueName] = []; ids.forEach((id) => { allLeagues[leagueName].push({ sid: id, region: country }); }); }); }); return allLeagues; } getLeagueTypeFromButtonId(id) { if (id.includes("senior leagues")) return LEAGUE_TYPES.SENIOR; if (id.includes("u18 world leagues")) return LEAGUE_TYPES.U18_WORLD; if (id.includes("u21 world leagues")) return LEAGUE_TYPES.U21_WORLD; if (id.includes("u23 world leagues")) return LEAGUE_TYPES.U23_WORLD; if (id.includes("u18 leagues")) return LEAGUE_TYPES.U18; if (id.includes("u21 leagues")) return LEAGUE_TYPES.U21; if (id.includes("u23 leagues")) return LEAGUE_TYPES.U23; return LEAGUE_TYPES.WORLD; } getLeaguesObjFromLeagueType(leagueType, country) { switch (leagueType) { case LEAGUE_TYPES.SENIOR: return country === "All" ? this.getAllLeagues(this.seniorLeagues) : this.seniorLeagues[country]; case LEAGUE_TYPES.WORLD: case LEAGUE_TYPES.U18_WORLD: case LEAGUE_TYPES.U21_WORLD: case LEAGUE_TYPES.U23_WORLD: return this.worldLeagues.World; case LEAGUE_TYPES.U18: case LEAGUE_TYPES.U21: case LEAGUE_TYPES.U23: return country === "All" ? this.getAllLeagues(this.uxxLeagues) : this.uxxLeagues[country]; default: return {}; } } getCountries(leagueType) { if ( leagueType === LEAGUE_TYPES.WORLD || leagueType === LEAGUE_TYPES.U18_WORLD || leagueType === LEAGUE_TYPES.U21_WORLD || leagueType === LEAGUE_TYPES.U23_WORLD ) { return ["World"]; } if (leagueType === LEAGUE_TYPES.SENIOR) { return Object.keys(this.seniorLeagues); } return Object.keys(this.uxxLeagues); } } class UIManager { constructor(leagueManager) { this.leagueManager = leagueManager; } initializeInterface() { const mainContainer = document.createElement("div"); mainContainer.id = "league-buttons-container"; const toggleBtn = this.createToggleButton(); toggleBtn.onclick = this.toggleLeagueButtons; CONSTANTS.BUTTON_NAMES.forEach(name => { const btn = document.createElement("button"); btn.className = "league-button"; btn.id = `league-button-${name.toLowerCase()}`; btn.textContent = name; btn.style.display = "none"; btn.onclick = () => { const leaguesModal = this.createLeaguesModal("leagues-modal", btn); document.body.appendChild(leaguesModal); }; mainContainer.appendChild(btn); }); mainContainer.appendChild(toggleBtn); document.querySelector(UI.SELECTORS.STADIUM_WRAPPER).appendChild(mainContainer); } createToggleButton() { const btn = document.createElement("button"); btn.id = "league-toggle-button"; btn.textContent = CONSTANTS.TOGGLE_TEXT_DOWN; return btn; } toggleLeagueButtons() { const container = document.getElementById("league-buttons-container"); const buttons = container.querySelectorAll(".league-button"); const toggleBtn = document.getElementById("league-toggle-button"); buttons.forEach(btn => { if (btn.style.display === "none") { btn.style.display = "block"; btn.classList.remove("fade-out"); btn.classList.add("fade-in"); toggleBtn.textContent = CONSTANTS.TOGGLE_TEXT_UP; } else { btn.classList.remove("fade-in"); btn.classList.add("fade-out"); setTimeout(() => { btn.style.display = "none"; }, 200); toggleBtn.textContent = CONSTANTS.TOGGLE_TEXT_DOWN; } }); } createLeaguesModal(modalId, button) { const leagueType = this.leagueManager.getLeagueTypeFromButtonId(button.id); const modal = document.createElement("div"); modal.id = modalId; const content = document.createElement("div"); content.id = "leagues-modal-content"; const title = document.createElement("h2"); title.id = "leagues-modal-title"; title.textContent = button.textContent; content.appendChild(title); const closeButton = document.createElement("button"); closeButton.id = "leagues-modal-close-button"; closeButton.textContent = "×"; closeButton.onclick = () => modal.remove(); content.appendChild(closeButton); const tablesContainer = document.createElement("div"); tablesContainer.id = "league-tables-container"; const countryDropdown = this.createCountryDropdown(leagueType); content.appendChild(countryDropdown); const tabContainer = this.createTabContainer(leagueType, countryDropdown.value, tablesContainer); content.appendChild(tabContainer); content.appendChild(tablesContainer); modal.appendChild(content); modal.onclick = (e) => { if (e.target === modal) { modal.remove(); } }; return modal; } createCountryDropdown(leagueType) { const dropdown = document.createElement("select"); dropdown.id = "country-dropdown"; if ( leagueType !== LEAGUE_TYPES.WORLD && leagueType !== LEAGUE_TYPES.U18_WORLD && leagueType !== LEAGUE_TYPES.U21_WORLD && leagueType !== LEAGUE_TYPES.U23_WORLD ) { const allOption = document.createElement("option"); allOption.value = "All"; allOption.text = "All"; dropdown.appendChild(allOption); } const countries = this.leagueManager.getCountries(leagueType); countries.forEach(country => { const option = document.createElement("option"); option.value = country; option.text = country; dropdown.appendChild(option); }); dropdown.onchange = () => { const tablesContainer = document.getElementById("league-tables-container"); const tabs = document.getElementById("league-tabs"); while (tabs.firstChild) { tabs.removeChild(tabs.firstChild); } while (tablesContainer.firstChild) { tablesContainer.removeChild(tablesContainer.firstChild); } const newTabs = this.createTabContainer(leagueType, dropdown.value, tablesContainer); tabs.parentNode.replaceChild(newTabs, tabs); if (newTabs.firstChild) { newTabs.firstChild.click(); } }; return dropdown; } createTabContainer(leagueType, country, tablesContainer) { const container = document.createElement("div"); container.id = "league-tabs"; const leagues = this.leagueManager.getLeaguesObjFromLeagueType(leagueType, country); Object.keys(leagues).forEach(league => { const tab = document.createElement("button"); tab.textContent = league; tab.onclick = async () => { while (tablesContainer.firstChild) { tablesContainer.removeChild(tablesContainer.firstChild); } const modalContent = document.getElementById("leagues-modal-content"); const loadingOverlay = document.createElement("div"); loadingOverlay.className = "loading-overlay"; const spinner = document.createElement("div"); spinner.className = "loader"; const loadingText = document.createElement("div"); loadingText.className = "loading-text"; loadingText.textContent = CONSTANTS.LOADING_TEXT; loadingOverlay.appendChild(spinner); loadingOverlay.appendChild(loadingText); modalContent.appendChild(loadingOverlay); loadingOverlay.style.display = "flex"; const leagueEntries = leagues[league]; const tables = await Promise.all( leagueEntries.map((entry, index) => { let sid, region; if (typeof entry === "object") { sid = entry.sid; region = entry.region; } else { sid = entry; region = country; } return this.fetchLeagueTable(sid, leagueType, index + 1, league, region); }) ); tables.sort((a, b) => a.divisionCount - b.divisionCount); tables.forEach(data => { if (data) { const hr = document.createElement("hr"); const title = this.createLeagueTitle(league, data.divisionCount, leagueType, data.region, league); tablesContainer.appendChild(hr); tablesContainer.appendChild(title); tablesContainer.appendChild(data.table); } }); loadingOverlay.style.display = "none"; loadingOverlay.remove(); }; container.appendChild(tab); }); return container; } async fetchLeagueTable(sid, leagueType, divisionCount, tabName, region) { try { const response = await fetch( `https://www.managerzone.com/ajax.php?p=league&type=${leagueType}&sid=${sid}&tid=${this.leagueManager.teamId}&sport=${this.leagueManager.sport}&sub=table` ); const html = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(html, "text/html"); const table = doc.querySelector(".nice_table"); if (!table) return null; this.setUpTableLinks(table); this.setUpHelpButton(table, sid, leagueType); return { table, divisionCount, region }; } catch (error) { console.error("Error fetching league table:", error); return null; } } setUpTableLinks(table) { const rows = table.querySelectorAll("tbody tr"); rows.forEach(row => { const link = row.querySelector('a[href^="/?p=league&type="]'); if (link) { const tid = link.href.match(/tid=(\d+)/); if (tid) { link.href = `/?p=team&tid=${tid[1]}`; } } const helpButton = row.querySelector(".help_button"); if (helpButton) { helpButton.style.pointerEvents = "none"; helpButton.style.opacity = "0.5"; helpButton.style.cursor = "default"; helpButton.onclick = (e) => { e.preventDefault(); return false; }; helpButton.href = "javascript:void(0);"; } }); } setUpHelpButton(table, sid, leagueType) { const secondRow = table.querySelector("tbody tr:nth-child(2)"); if (!secondRow) return; const helpButton = secondRow.querySelector(".help_button"); const teamLink = secondRow.querySelector("a[onclick*='purchaseChallenge']"); if (helpButton && teamLink) { const tid = teamLink .getAttribute("onclick") .split(",")[2].replace(/[ ';)]/g, ""); helpButton.removeAttribute("onclick"); helpButton.onclick = () => this.handleExtraLeagueData(sid, leagueType, tid); } } async handleExtraLeagueData(sid, leagueType, tid) { const response = await fetch( `https://www.managerzone.com/ajax.php?p=extraLeague&sub=division_runner_ups&type=${leagueType}&sid=${sid}&tid=${tid}&sport=${this.leagueManager.sport}` ); const html = await response.text(); const modal = document.createElement("div"); modal.id = "extra-league-data-modal"; modal.className = "leagues-modal"; const content = document.createElement("div"); content.className = "leagues-modal-content"; content.innerHTML = html; modal.appendChild(content); document.body.appendChild(modal); modal.onclick = (event) => { if (event.target === modal) modal.remove(); }; } createLeagueTitle(selectedLeague, divisionCount, leagueType, region) { const p = document.createElement("p"); p.classList.add("league-table-title"); if (!selectedLeague.startsWith("Division")) { p.textContent = selectedLeague; } else { const theDivision = selectedLeague + "." + divisionCount; p.textContent = theDivision.replace("Division", "div"); } p.textContent += " " + leagueType.charAt(0).toUpperCase() + leagueType.slice(1); if (region && region !== "World") { p.textContent += " " + region; } if (p.textContent.includes("_")) { p.textContent = p.textContent.replace("_", " "); } return p; } } const infoAboutTeam = document.querySelector(UI.SELECTORS.TEAM_INFO); const teamStadiumWrapper = document.querySelector(UI.SELECTORS.STADIUM_WRAPPER); if (infoAboutTeam && teamStadiumWrapper) { const leagueManager = new LeagueManager(); const uiManager = new UIManager(leagueManager); uiManager.initializeInterface(); } })();