您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds team badges and country flags to league and cup tables
// ==UserScript== // @name MZ - Badges & Flags // @namespace douglaskampl // @version 2.0 // @description Adds team badges and country flags to league and cup tables // @author Douglas // @match https://www.managerzone.com/?p=league* // @match https://www.managerzone.com/?p=friendlyseries* // @match https://www.managerzone.com/?p=private_cup* // @match https://www.managerzone.com/?p=cup* // @match https://www.managerzone.com/?p=match&sub=played // @grant none // @run-at document-idle // @license MIT // ==/UserScript== (() => { 'use strict'; /** * Configuration for script features. * @type {{showBadges: boolean, showFlags: boolean}} */ const config = { showBadges: true, showFlags: true }; /** * Fetches the country code for a given team ID from the ManagerZone API. * @param {string} teamId The ID of the team. * @returns {Promise<string|null>} A promise that resolves to the two-letter country code or null if an error occurs. */ const getCountryCode = async (teamId) => { try { const response = await fetch(`https://www.managerzone.com/xml/manager_data.php?sport_id=1&team_id=${teamId}`); if (!response.ok) { throw new Error(`HTTP error status: ${response.status}`); } const xmlText = await response.text(); const parser = new DOMParser(); const xmlDoc = parser.parseFromString(xmlText, "application/xml"); const userData = xmlDoc.querySelector('UserData'); if (userData) { const countryShortname = userData.getAttribute('countryShortname'); if (countryShortname) { return countryShortname; } } return null; } catch (error) { console.error(`[MZ-B&F] Failed to fetch country for team ID ${teamId}:`, error); return null; } }; /** * Creates and configures a team badge image element. * @param {string} teamId The ID of the team. * @returns {HTMLImageElement} The configured image element for the badge. */ const createBadgeElement = (teamId) => { const badgeImg = document.createElement('img'); badgeImg.src = `https://www.managerzone.com/dynimg/badge.php?team_id=${teamId}&sport=soccer&location=team_main`; badgeImg.width = 10; badgeImg.height = 15; badgeImg.className = 'mz-enhancer-badge'; badgeImg.style.marginRight = '4px'; badgeImg.style.verticalAlign = 'middle'; return badgeImg; }; /** * Creates and configures a flag image element. * @param {string} countryCode The two-letter country code. * @returns {HTMLImageElement} The configured image element for the flag. */ const createFlagElement = (countryCode) => { const flagImg = document.createElement('img'); flagImg.src = `https://www.managerzone.com/img/flags/12/${countryCode.toLowerCase()}.png`; flagImg.width = 12; flagImg.height = 12; flagImg.title = countryCode; flagImg.className = 'mz-enhancer-flag'; flagImg.style.marginRight = '4px'; flagImg.style.verticalAlign = 'middle'; return flagImg; }; /** * Adds a team badge before the specified team link element if it doesn't already exist. * @param {HTMLAnchorElement} teamLink The team anchor element. * @param {string} teamId The ID of the team. */ const addBadge = (teamLink, teamId) => { if (!config.showBadges || teamLink.previousElementSibling?.classList.contains('mz-enhancer-badge')) { return; } const badgeElement = createBadgeElement(teamId); teamLink.before(badgeElement); }; /** * Fetches and adds a country flag to the specified table cell if it doesn't already exist. * @param {HTMLTableCellElement} teamCell The table cell containing the team link. * @param {string} teamId The ID of the team. */ const addFlag = async (teamCell, teamId) => { if (!config.showFlags || teamCell.querySelector('.mz-enhancer-flag')) { return; } const countryCode = await getCountryCode(teamId); if (countryCode) { const flagElement = createFlagElement(countryCode); teamCell.prepend(flagElement); } }; /** * Processes a single table row to add badges and flags. * @param {HTMLTableRowElement} row The table row element to process. */ const processTableRow = (row) => { const teamLink = row.querySelector('a[href*="p=team&tid="]'); if (!teamLink) return; const teamCell = teamLink.closest('td'); const urlParams = new URLSearchParams(teamLink.search); const teamId = urlParams.get('tid'); const isLeaguePage = window.location.search.includes('p=league'); if (!teamCell || !teamId) return; addBadge(teamLink, teamId); if (!isLeaguePage) { addFlag(teamCell, teamId); } }; /** * Finds and processes all tables within a container. * @param {Element} container The parent element to search within. */ const processTables = (container) => { const tables = container.matches('table.nice_table') ? [container] : container.querySelectorAll('table.nice_table'); tables.forEach(table => { if (table.dataset.mzEnhanced) return; table.dataset.mzEnhanced = 'true'; const rows = table.querySelectorAll('tbody tr'); rows.forEach((row, index) => { setTimeout(() => processTableRow(row), index * 100); }); }); }; /** * The callback function for the MutationObserver. * @param {MutationRecord[]} mutationsList An array of mutations. */ const observerCallback = (mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { mutation.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { processTables(node); } }); } } }; processTables(document.body); const observer = new MutationObserver(observerCallback); observer.observe(document.body, { childList: true, subtree: true }); })();