mz - World League Standings

Display all leagues from a country or region, grouped by div, on a single view

// ==UserScript==
// @name          mz - World League Standings
// @version       3.0
// @description   Display all leagues from a country or region, grouped by div, on a single view
// @author        Douglas Vieira
// @match         *://www.managerzone.com/?p=team
// @icon          https://www.google.com/s2/favicons?sz=64&domain=managerzone.com
// @grant         GM_addStyle
// @license       MIT
// @namespace https://greasyfork.org/users/1088808
// ==/UserScript==

(function () {
  const mainContainer = document.createElement("div");

  const infoAboutTeam = document.getElementById("infoAboutTeam");
  const teamStadiumWrapper = document.getElementById("team-stadium-wrapper");

  const sport = new URL(
    document.querySelector("#shortcut_link_thezone").href
  ).searchParams.get("sport");

  const seniorLeagues = getSeniorLeagues();

  const worldLeagues = {
    World: getWorldLeaguesObj(),
  };

  const uxxLeagues = getUxxLeagues();

  const buttonNames = [
    "Senior Leagues",
    "World Leagues",
    "U18 World Leagues",
    "U21 World Leagues",
    "U23 World Leagues",
    "U18 Leagues",
    "U21 Leagues",
    "U23 Leagues",
  ];

  const teamId = RegExp(/\((\d+)\)/).exec(
    infoAboutTeam.querySelector("dd").textContent
  )[1];

  if (infoAboutTeam && teamStadiumWrapper) {
    appendLeagueButtonsToTeamPage();
  }

  function appendLeagueButtonsToTeamPage() {
    for (let i = 0; i < 8; ++i) {
      const button = document.createElement("button");
      setupButton(
        button,
        `league-button-${buttonNames[i].toLocaleLowerCase()}`,
        buttonNames[i]
      );
      mainContainer.appendChild(button);
    }
    teamStadiumWrapper.appendChild(
      setupMainContainer(mainContainer, "league-buttons-container")
    );
  }

  async function fetchLeagueTable(sid, leagueType, divisionCount, country) {
    try {
      const response = await fetch(
        `https://www.managerzone.com/ajax.php?p=league&type=${leagueType}&sid=${sid}&tid=${teamId}&sport=${sport}&sub=table`
      );
      const html = await response.text();
      const parser = new DOMParser();
      const doc = parser.parseFromString(html, "text/html");

      const niceTable = doc.querySelector(".nice_table");
      niceTable.style.margin = "16px auto";
      niceTable.style.width = "60%";

      const rows = niceTable.querySelectorAll('tbody tr');
      for (const row of rows) {
        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]}`;
          }
        }
      }

      handleHelpButton(niceTable, sid, leagueType);

      return {
        table: niceTable,
        divisionCount: divisionCount,
        country: country,
      };
    } catch (error) {
      console.error("Error: ", error);
      return null;
    }
  }

  function handleHelpButton(table, sid, leagueType) {
    const secondRow = table.querySelector("tbody tr:nth-child(2)");
    const helpButton = secondRow.querySelector(".help_button");
    const teamLink = secondRow.querySelector("a[onclick*='purchaseChallenge']");
    const tid = teamLink
      ? teamLink
          .getAttribute("onclick")
          .split(",")[2]
          .replace(/[ ';)]/g, "")
      : null;

    if (helpButton && tid) {
      helpButton.removeAttribute("onclick");
      helpButton.addEventListener("click", (event) => {
        event.preventDefault();
        fetchExtraLeagueData(sid, leagueType, tid);
      });
    }
  }

  function createLeaguesModal(modalId, button) {
    const leagueType = getLeagueTypeFromButtonId(button.id);

    const leaguesModalTitle = button.textContent;

    const leaguesModal = document.createElement("div");
    setupModal(leaguesModal, modalId);

    const leaguesModalContent = addContentToLeaguesModal(leaguesModal);
    ensureContentIsCentered(leaguesModalContent);

    const leagueTablesContainer =
      addTablesContainerToLeaguesModal(leaguesModalContent);

    const dropdownAndTablesContainer = document.createElement("div");
    const countryDropdown = createCountryDropdown(
      leagueType,
      dropdownAndTablesContainer,
      leagueTablesContainer
    );
    leaguesModalContent.appendChild(countryDropdown);

    const selectedCountry = countryDropdown.value;
    const leaguesObject = getLeaguesObjFromLeagueType(
      leagueType,
      selectedCountry
    );

    addOtherComponentsToLeaguesModal(
      leaguesModal,
      leaguesModalContent,
      leaguesModalTitle,
      leagueTablesContainer,
      leagueType,
      leaguesObject
    );

    return leaguesModal;
  }

  function addContentToLeaguesModal(modal) {
    const modalContent = document.createElement("div");
    setupLeaguesModalContent(modalContent, "leagues-modal-content");
    modal.appendChild(modalContent);
    return modalContent;
  }

  function addTablesContainerToLeaguesModal(modalContent) {
    const leagueTablesContainer = document.createElement("div");
    leagueTablesContainer.id = "league-tables-container";
    modalContent.appendChild(leagueTablesContainer);
    return leagueTablesContainer;
  }

  function addOtherComponentsToLeaguesModal(
    modal,
    modalContent,
    modalTitle,
    leagueTablesContainer,
    leagueType,
    leaguesObject
  ) {
    const tablesContainer = document.createElement("div");
    addModalTitleToLeaguesModal(modalContent, modalTitle);
    addTabsToLeaguesModal(
      modalContent,
      leagueType,
      leaguesObject,
      leagueTablesContainer
    );
    addCloseButtonToLeaguesModal(modal, modalContent);
    tablesContainer.appendChild(leagueTablesContainer);
    modalContent.appendChild(tablesContainer);
  }

  function addModalTitleToLeaguesModal(modalContent, titleText) {
    const title = document.createElement("h2");
    setupLeaguesModalTitle(title, "leagues-modal-title", titleText);
    modalContent.appendChild(title);
  }

  function addTabsToLeaguesModal(
    container,
    leagueType,
    leaguesObj,
    leagueTablesContainer
  ) {
    const tabContainer = document.createElement("div");
    setupLeaguesTabs(
      tabContainer,
      "leagues-tabs",
      leagueType,
      leaguesObj,
      leagueTablesContainer
    );
    container.appendChild(tabContainer);
  }

  function addCloseButtonToLeaguesModal(modal, modalContent) {
    const closeButton = document.createElement("button");
    setupCloseButton(closeButton, "leagues-modal-close-button", modal);
    modalContent.appendChild(closeButton);
  }

  function ensureContentIsCentered(modalContent) {
    const initialMarginTop = Math.max(
      (window.innerHeight - modalContent.offsetHeight) / 2,
      0
    );
    modalContent.style.marginTop = initialMarginTop + "px";

    window.addEventListener("scroll", function () {
      const newMarginTop = Math.max(
        (window.innerHeight - modalContent.offsetHeight) / 2,
        0
      );
      modalContent.style.marginTop = newMarginTop + "px";
    });
  }

  function setupModal(modal, id) {
    modal.id = id;
    modal.style.position = "fixed";
    modal.style.zIndex = "1";
    modal.style.left = "0";
    modal.style.top = "0";
    modal.style.width = "100%";
    modal.style.height = "100%";
    modal.style.display = "flex";
    modal.style.justifyContent = "center";
    modal.style.alignItems = "center";
    modal.style.backgroundColor = "rgba(0,0,0,0.8)";
    modal.style.opacity = "0";
    modal.style.transition = "opacity 0.5s ease-in-out";
    setTimeout(function () {
      modal.style.opacity = "1";
    }, 0);
  }

  function setupLeaguesModalContent(modalContent, id) {
    modalContent.id = id;
    modalContent.style.backgroundColor = "#fefefe";
    modalContent.style.backgroundImage =
      "url('https://s1.ax1x.com/2023/06/25/pCNmCSH.jpg')";
    modalContent.style.backgroundSize = "cover";
    modalContent.style.backgroundPosition = "center";
    modalContent.style.margin = "0 auto";
    modalContent.style.padding = "20px";
    modalContent.style.border = "1px solid #888";
    modalContent.style.width = "80%";
    modalContent.style.position = "relative";
    modalContent.style.overflowY = "auto";
    modalContent.style.maxHeight = "80vh";
    ensureContentIsCentered(modalContent);
  }

  function setupLeaguesModalTitle(title, id, textContent) {
    title.id = id;
    title.textContent = textContent;
    title.style.textAlign = "center";
    title.style.fontFamily = "Montserrat, sans-serif";
    title.style.color = "navy";
  }

  function setupCloseButton(button, id, modal) {
    button.id = id;
    button.textContent = "X";
    button.style.position = "absolute";
    button.style.top = "10px";
    button.style.right = "10px";
    button.style.fontFamily = "Arial, sans-serif";
    button.style.fontSize = "20px";
    button.style.fontWeight = "bold";
    button.style.color = "#000";
    button.style.backgroundColor = "transparent";
    button.style.border = "none";
    button.style.cursor = "pointer";
    button.onclick = function () {
      modal.style.opacity = "0";
      setTimeout(function () {
        document.body.removeChild(modal);
      }, 500);
    };
  }

  function setupLeaguesTabs(
    tabContainer,
    id,
    leagueType,
    leagues,
    leagueTablesContainer
  ) {
    tabContainer.id = id;
    for (const league in leagues) {
      const tab = document.createElement("button");
      setupTab(
        tab,
        `tab-${league.toLocaleLowerCase().replace(" ", "")}`,
        league
      );
      const tabName = league;

      tab.onclick = async function () {
        updateLeaguesModal(leagueTablesContainer);
        const selectedCountry =
          document.getElementById("country-dropdown").value;

        const selectedDivision = this.textContent;

        const leagues = getLeaguesObjFromLeagueType(
          leagueType,
          selectedCountry
        );
        const leagueIds = leagues[selectedDivision];
        const fetchPromises = leagueIds.map((sid, index) =>
          fetchLeagueTable(sid, leagueType, index + 1, selectedCountry)
        );
        const tablesData = await Promise.all(fetchPromises);
        tablesData.sort((a, b) => a.divisionCount - b.divisionCount);
        tablesData.forEach((data) => {
          if (data !== null) {
            leagueTablesContainer.appendChild(document.createElement("hr"));
            leagueTablesContainer.appendChild(
              createLeagueTitle(
                selectedDivision,
                data.divisionCount,
                leagueType,
                selectedCountry,
                tabName,
                seniorLeagues
              )
            );
            leagueTablesContainer.appendChild(data.table);
            data.table.id = `${leagueType}-${selectedCountry
              .toLocaleLowerCase()
              .replace(" ", "")}-${data.divisionCount}`;
          }
        });
      };

      tabContainer.appendChild(tab);
    }
  }

  function getLeagueTypeFromButtonId(id) {
    if (id.includes("senior leagues")) {
      return "senior";
    } else if (id.includes("u18 world leagues")) {
      return "u18_world";
    } else if (id.includes("u21 world leagues")) {
      return "u21_world";
    } else if (id.includes("u23 world leagues")) {
      return "u23_world";
    } else if (id.includes("u18 leagues")) {
      return "u18";
    } else if (id.includes("u21 leagues")) {
      return "u21";
    } else if (id.includes("u23 leagues")) {
      return "u23";
    } else {
      return "world";
    }
  }

  function getLeaguesObjFromLeagueType(leagueType, country) {
    let leagues;
    switch (leagueType) {
      case "senior":
        leagues =
          country === "All"
            ? getAllLeagues(seniorLeagues)
            : seniorLeagues[country];
        break;
      case "world":
      case "u18_world":
      case "u21_world":
      case "u23_world":
        leagues = worldLeagues.World;
        break;
      case "u18":
      case "u21":
      case "u23":
        leagues =
          country === "All" ? getAllLeagues(uxxLeagues) : uxxLeagues[country];
        break;
      default:
        break;
    }
    return leagues;
  }

  function getAllLeagues(leaguesObj) {
    const allLeagues = {};
    for (const country in leaguesObj) {
      for (const league in leaguesObj[country]) {
        if (!allLeagues[league]) {
          allLeagues[league] = [];
        }
        allLeagues[league] = allLeagues[league].concat(
          leaguesObj[country][league]
        );
      }
    }
    return allLeagues;
  }

  function getCountries(leagueType) {
    let countries;
    switch (leagueType) {
      case "senior":
        countries = Object.keys(seniorLeagues);
        break;
      case "world":
      case "u18_world":
      case "u21_world":
      case "u23_world":
        countries = ["World"];
        break;
      case "u18":
      case "u21":
      case "u23":
        countries = Object.keys(uxxLeagues);
        break;
      default:
        break;
    }
    return countries;
  }

  function updateLeaguesModal(leagueTablesContainer) {
    while (leagueTablesContainer.firstChild) {
      leagueTablesContainer.removeChild(leagueTablesContainer.firstChild);
    }
  }

  function createLeagueTitle(
    selectedLeague,
    divisionCount,
    type,
    country,
    tabName,
    seniorLeagues
  ) {
    const p = document.createElement("p");

    if (!selectedLeague.startsWith("Division")) {
      p.textContent = selectedLeague;
    } else {
      const theDivision = selectedLeague + "." + divisionCount;
      p.textContent = theDivision.replace("Division", "div");
    }

    p.textContent += " " + type.charAt(0).toUpperCase() + type.slice(1);

    if (
      (type === "senior" ||
        type === "u18" ||
        type === "u21" ||
        type === "u23") &&
      country !== "All"
    ) {
      p.textContent += " " + country;
    }

    if (p.textContent.includes("All")) {
      p.textContent = p.textContent.replace("All", "");
    }

    if (p.textContent.includes("_")) {
      p.textContent = p.textContent.replace("_", " ");
    }

    if (type === "senior" && country === "All" && tabName === "Top Division") {
      const keysOfSeniorLeagues = Object.keys(seniorLeagues);
      p.textContent += " " + keysOfSeniorLeagues[divisionCount - 1];
    }

    const tabNameEndsWithNumber = /\d$/.test(tabName);
    let tabNameNumber = 0;
    if (tabNameEndsWithNumber) {
      tabNameNumber = parseInt(tabName.charAt(tabName.length - 1));
    }

    if (!type.includes("world") && tabNameEndsWithNumber) {
      if (RegExp(/\.\d+/).exec(p.textContent)) {
        p.textContent = p.textContent.replace(/\.\d+/, (match) => {
          const number = parseInt(match.slice(1));
          const divisor = Math.pow(3, tabNameNumber);
          if (number > divisor) {
            const replacement = number % divisor;
            return `.${replacement === 0 ? divisor : replacement}`;
          }
          return match;
        });
      }
    }

    p.style.fontFamily = "Montserrat, sans-serif";
    p.style.fontWeight = "bold";
    p.style.textAlign = "center";
    return p;
  }

  function setupButton(button, id, textContent) {
    button.id = id;
    button.textContent = textContent;

    styleButton(button);
    setupButtonAnimations(button);

    button.onclick = function () {
      const leaguesModal = createLeaguesModal("leagues-modal", button);
      appendAndShowOrHideModal(leaguesModal);
    };
  }

  function styleButton(button) {
    button.style.margin = "4px";
    button.style.padding = "8px 16px";
    button.style.border = "none";
    button.style.borderRadius = "12px";
    button.style.backgroundColor = "#000080";
    button.style.color = "white";
    button.style.fontFamily = "Montserrat, sans-serif";
    button.style.fontSize = "12px";
    button.style.cursor = "pointer";
    button.style.boxShadow = "0px 2px 6px rgba(0, 0, 0, 0.3)";
  }

  function setupButtonAnimations(button) {
    button.onmouseover = function () {
      button.style.backgroundColor = "#27285C";
      button.style.transform = "scale(1.05)";
    };
    button.onmouseout = function () {
      button.style.backgroundColor = "#000080";
      button.style.transform = "scale(1)";
    };
    button.onmousedown = function () {
      button.style.transform = "scale(0.95)";
    };
    button.onmouseup = function () {
      button.style.transform = "scale(1)";
    };
  }

  function appendAndShowOrHideModal(modal) {
    document.body.appendChild(modal);
    window.onclick = function (event) {
      if (event.target == modal) {
        modal.style.opacity = "0";
        setTimeout(function () {
          document.body.removeChild(modal);
        }, 500);
      }
    };
  }

  function setupMainContainer(container, id) {
    container.id = id;
    container.style.display = "flex";
    container.style.flexDirection = "column";
    container.style.justifyContent = "center";
    container.style.alignItems = "center";
    container.style.marginTop = "20px";
    return container;
  }

  function setupTab(tab, id, text) {
    tab.textContent = text;
    tab.id = id;
    tab.style.margin = "4px";
  }

  function fetchExtraLeagueData(sid, leagueType, tid) {
    fetch(
      `https://www.managerzone.com/ajax.php?p=extraLeague&sub=division_runner_ups&type=${leagueType}&sid=${sid}&tid=${tid}&sport=soccer`
    )
      .then((response) => response.text())
      .then((html) => {
        const extraLeagueDataModal = createExtraLeagueDataModal(html);
        document.body.appendChild(extraLeagueDataModal);
      })
      .catch((error) => console.error("Error: ", error));
  }

  function createExtraLeagueDataModal(html) {
    const modal = document.createElement("div");
    setupModal(modal, "extra-league-data-modal");

    const extraDataDiv = document.createElement("div");
    extraDataDiv.innerHTML = html;
    extraDataDiv.style.width = "60%";
    modal.appendChild(extraDataDiv);

    window.addEventListener("click", function (event) {
      if (event.target == modal) {
        modal.style.display = "none";
      }
    });

    return modal;
  }

  function createCountryDropdown(
    leagueType,
    tabContainer,
    leagueTablesContainer
  ) {
    const dropdown = document.createElement("select");
    dropdown.id = "country-dropdown";
    addPotentialAllOpt(dropdown, leagueType);

    const countries = getCountries(leagueType);
    countries.forEach((country) => {
      const option = document.createElement("option");
      option.value = country;
      option.text = country;
      dropdown.appendChild(option);
    });

    dropdown.onchange = function () {
      const selectedCountry = this.value;
      const leagues = getLeaguesObjFromLeagueType(leagueType, selectedCountry);

      while (tabContainer.firstChild) {
        tabContainer.removeChild(tabContainer.firstChild);
      }

      setupLeaguesTabs(
        tabContainer,
        "leagues-tabs",
        leagueType,
        leagues,
        leagueTablesContainer
      );

      while (leagueTablesContainer.firstChild) {
        leagueTablesContainer.removeChild(leagueTablesContainer.firstChild);
      }

      if (tabContainer.firstChild) {
        tabContainer.firstChild.click();
      }
    };

    return dropdown;
  }

  function addPotentialAllOpt(dropdown, leagueType) {
    if (
      !["world", "u18_world", "u21_world", "u23_world"].includes(leagueType)
    ) {
      const allOption = document.createElement("option");
      allOption.value = "All";
      allOption.text = "All";
      dropdown.appendChild(allOption);
    }
  }

  const myTeamLeaguesInfo = Array.from(infoAboutTeam.querySelectorAll("dd"))
    .slice(5, 14)
    .reduce((info, dd, index) => {
      const leagueType = dd
        .querySelector(".teamExpText")
        .textContent.trim()
        .toLowerCase();

      const leagueValue = dd.querySelector("strong a").textContent.trim();

      let division;
      if (index === 0 || leagueType === "league") {
        division = isNaN(parseInt(leagueValue[0], 10))
          ? "Top Division"
          : `Division ${parseInt(leagueValue[0], 10)}`;
      } else if (
        [
          "world league",
          "u18 world league",
          "u21 world league",
          "u23 world league",
        ].includes(leagueType)
      ) {
        division = leagueValue.startsWith("Top")
          ? "Top Series"
          : `Division ${parseInt(
              leagueValue.split("div")[1].split(".")[0],
              10
            )}`;
      } else {
        division = leagueValue.includes("div")
          ? `Division ${parseInt(
              leagueValue.split("div")[1].split(".")[0],
              10
            )}`
          : "Top Division";
      }

      info[leagueType] = division;
      return info;
    }, {});

  function getSeniorLeagues() {
    let countries;

    if (sport === "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 },
      ];
    } else {
      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 },
      ];
    }

    let leagues = {};

    for (let country of countries) {
      leagues[country.name] = {
        "Top Division": [country.start],
      };
    }

    const sortedLeagues = Object.keys(leagues)
      .sort()
      .reduce((result, key) => {
        result[key] = leagues[key];
        return result;
      }, {});

    return sortedLeagues;
  }

  function getWorldLeaguesObj() {
    const leagues = {};
    let start = 1;

    for (let i = 0; i <= 4; ++i) {
      const divisionName = i === 0 ? "Top Series" : `Division ${i}`;
      leagues[divisionName] = [];
      const numLeagues = Math.pow(3, i);

      for (let j = 0; j < numLeagues; ++j) {
        leagues[divisionName].push(start++);
      }
    }

    return leagues;
  }

  function getUxxLeagues() {
    let UxxRegions;

    if (sport === "soccer") {
      UxxRegions = [
        { 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 },
      ];
    } else {
      UxxRegions = [
        { name: "Northern Europe", start: 1 },
        { name: "Southern Europe", start: 122 },
        { name: "Rest of the World", start: 243 },
      ];
    }

    let leagues = {};

    for (let region of UxxRegions) {
      leagues[region.name] = {
        "Top Division": [region.start],
        "Division 1": [],
        "Division 2": [],
      };

      for (let i = 1; i <= 12; i++) {
        if (i <= 3) {
          leagues[region.name]["Division 1"].push(region.start + i);
        } else {
          leagues[region.name]["Division 2"].push(region.start + i);
        }
      }
    }

    return leagues;
  }
})();

GM_addStyle(`
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap');
`);