MZ Tactics Selector

Adds a dropdown menu with overused tactics.

目前为 2023-06-07 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name MZ Tactics Selector
  3. // @namespace essenfc
  4. // @version 4.1
  5. // @description Adds a dropdown menu with overused tactics.
  6. // @author Douglas Vieira
  7. // @match https://www.managerzone.com/?p=tactics
  8. // @match https://www.managerzone.com/?p=national_teams&sub=tactics&type=*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=managerzone.com
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15. const fontLink = document.createElement("link");
  16. fontLink.href =
  17. "https://fonts.googleapis.com/css2?family=Montserrat&display=swap";
  18. fontLink.rel = "stylesheet";
  19. document.head.appendChild(fontLink);
  20.  
  21. let modal;
  22.  
  23. (function () {
  24. "use strict";
  25.  
  26. let dropdownTactics = [];
  27.  
  28. const defaultTacticsDataUrl =
  29. "https://raw.githubusercontent.com/douglasdotv/tactics-selector/main/tactics.json?callback=?";
  30.  
  31. const outfieldPlayersSelector =
  32. ".fieldpos.fieldpos-ok.ui-draggable:not(.substitute):not(.goalkeeper):not(.substitute.goalkeeper), .fieldpos.fieldpos-collision.ui-draggable:not(.substitute):not(.goalkeeper):not(.substitute.goalkeeper)";
  33.  
  34. window.addEventListener("load", function () {
  35. const tacticsSelectorDiv = createTacSelDiv();
  36. const dropdown = createDropdownMenu();
  37. const dropdownDescription = createDropdownDescription();
  38. const addNewTacticBtn = createAddNewTacticButton();
  39. const deleteTacticBtn = createDeleteTacticButton();
  40. const renameTacticBtn = createRenameTacticButton();
  41. const updateTacticBtn = createUpdateTacticButton();
  42. const clearTacticsBtn = createClearTacticsButton();
  43. const resetTacticsBtn = createResetTacticsButton();
  44. const importTacticsBtn = createImportTacticsButton();
  45. const exportTacticsBtn = createExportTacticsButton();
  46. const aboutBtn = createAboutButton();
  47. const hiBtn = createHiButton();
  48.  
  49. appendChildren(tacticsSelectorDiv, [
  50. dropdownDescription,
  51. dropdown,
  52. addNewTacticBtn,
  53. deleteTacticBtn,
  54. renameTacticBtn,
  55. updateTacticBtn,
  56. clearTacticsBtn,
  57. resetTacticsBtn,
  58. importTacticsBtn,
  59. exportTacticsBtn,
  60. aboutBtn,
  61. hiBtn,
  62. ]);
  63.  
  64. if (isSoccerTacticsPage()) {
  65. insertAfterElement(
  66. tacticsSelectorDiv,
  67. document.getElementById("tactics_box")
  68. );
  69. }
  70.  
  71. modal = createInfoModal();
  72. document.body.appendChild(modal);
  73. document.addEventListener("click", function (event) {
  74. if (modal.style.display === "block" && !modal.contains(event.target)) {
  75. modal.style.display = "none";
  76. }
  77. });
  78.  
  79. fetchTacticsFromLocalStorage()
  80. .then((data) => {
  81. dropdownTactics = data.tactics;
  82.  
  83. dropdownTactics.sort((a, b) => {
  84. return a.name.localeCompare(b.name);
  85. });
  86.  
  87. addTacticsToDropdown(dropdown, dropdownTactics);
  88.  
  89. dropdown.addEventListener("change", function () {
  90. handleTacticSelection(this.value);
  91. });
  92. })
  93. .catch((err) => {
  94. console.error("Couldn't fetch data from json: ", err);
  95. });
  96. });
  97.  
  98. function createTacSelDiv() {
  99. const myDiv = document.createElement("div");
  100. myDiv.id = "tactics_selector_div";
  101. myDiv.style.width = "100%";
  102. myDiv.style.display = "flex";
  103. myDiv.style.flexWrap = "wrap";
  104. myDiv.style.alignItems = "center";
  105. myDiv.style.justifyContent = "flex-start";
  106. myDiv.style.marginTop = "6px";
  107. myDiv.style.marginLeft = "6px";
  108. return myDiv;
  109. }
  110.  
  111. // _____Dropdown Menu_____
  112.  
  113. function createDropdownMenu() {
  114. const dropdown = document.createElement("select");
  115. setupDropdownMenu(dropdown);
  116.  
  117. const placeholderOption = createPlaceholderOption();
  118. appendChildren(dropdown, [placeholderOption]);
  119.  
  120. return dropdown;
  121. }
  122.  
  123. function setupDropdownMenu(dropdown) {
  124. dropdown.id = "tacticsDropdown";
  125. dropdown.style.fontSize = "12px";
  126. dropdown.style.fontFamily = "Montserrat, sans-serif";
  127. dropdown.style.border = "2px solid #000";
  128. dropdown.style.borderRadius = "2px";
  129. dropdown.style.background = "linear-gradient(to right, #add8e6, #e6f7ff)";
  130. dropdown.style.color = "#000";
  131. dropdown.style.boxShadow = "3px 3px 5px rgba(0, 0, 0, 0.2)";
  132. dropdown.style.cursor = "pointer";
  133. dropdown.style.outline = "none";
  134. dropdown.style.margin = "6px";
  135. }
  136.  
  137. function createPlaceholderOption() {
  138. const placeholderOption = document.createElement("option");
  139. placeholderOption.value = "";
  140. placeholderOption.text = "";
  141. placeholderOption.disabled = true;
  142. placeholderOption.selected = true;
  143. return placeholderOption;
  144. }
  145.  
  146. function createDropdownDescription() {
  147. const description = document.createElement("span");
  148. description.textContent = "Select a tactic: ";
  149. description.style.fontFamily = "Montserrat, sans-serif";
  150. description.style.fontSize = "12px";
  151. description.style.color = "#000";
  152. return description;
  153. }
  154.  
  155. function createHiButton() {
  156. const button = document.createElement("button");
  157. button.id = "hiButton";
  158. button.textContent = "";
  159. button.style.visibility = "hidden";
  160.  
  161. button.addEventListener("click", function () {
  162. const presetDropdown = document.getElementById("tactics_preset");
  163. presetDropdown.value = "5-3-2";
  164. presetDropdown.dispatchEvent(new Event("change"));
  165. });
  166.  
  167. return button;
  168. }
  169.  
  170. async function fetchTacticsFromLocalStorage() {
  171. const storedTactics = GM_getValue("ls_tactics");
  172. if (storedTactics) {
  173. return storedTactics;
  174. } else {
  175. const jsonTactics = await fetchTacticsFromJson();
  176. storeTacticsInLocalStorage(jsonTactics);
  177. return jsonTactics;
  178. }
  179. }
  180.  
  181. async function fetchTacticsFromJson() {
  182. const response = await fetch(defaultTacticsDataUrl);
  183. return await response.json();
  184. }
  185.  
  186. function storeTacticsInLocalStorage(data) {
  187. GM_setValue("ls_tactics", data);
  188. }
  189.  
  190. function addTacticsToDropdown(dropdown, tactics) {
  191. for (const tactic of tactics) {
  192. const option = document.createElement("option");
  193. option.value = tactic.name;
  194. option.text = tactic.name;
  195. dropdown.appendChild(option);
  196. }
  197. }
  198.  
  199. function handleTacticSelection(tactic) {
  200. let outfieldPlayers = Array.from(
  201. document.querySelectorAll(outfieldPlayersSelector)
  202. );
  203.  
  204. const selectedTactic = dropdownTactics.find(
  205. (tacticData) => tacticData.name === tactic
  206. );
  207.  
  208. if (selectedTactic) {
  209. if (outfieldPlayers.length < 10) {
  210. const hiButton = document.getElementById("hiButton");
  211. hiButton.click();
  212. setTimeout(() => rearrangePlayers(selectedTactic.coordinates), 1);
  213. } else {
  214. rearrangePlayers(selectedTactic.coordinates);
  215. }
  216. }
  217. }
  218.  
  219. function rearrangePlayers(coordinates) {
  220. const outfieldPlayers = Array.from(
  221. document.querySelectorAll(outfieldPlayersSelector)
  222. );
  223.  
  224. for (let i = 0; i < outfieldPlayers.length; ++i) {
  225. outfieldPlayers[i].style.left = coordinates[i][0] + "px";
  226. outfieldPlayers[i].style.top = coordinates[i][1] + "px";
  227.  
  228. if (outfieldPlayers[i].classList.contains("fieldpos-collision")) {
  229. outfieldPlayers[i].classList.remove("fieldpos-collision");
  230. outfieldPlayers[i].classList.add("fieldpos-ok");
  231. }
  232. }
  233. }
  234.  
  235. // _____Add new tactic_____
  236.  
  237. function createAddNewTacticButton() {
  238. const button = document.createElement("button");
  239. button.id = "addNewTacticButton";
  240. button.textContent = "Add current tactic";
  241. button.style.fontFamily = "Montserrat, sans-serif";
  242. button.style.fontSize = "12px";
  243. button.style.color = "#000";
  244. button.style.marginLeft = "6px";
  245. button.style.cursor = "pointer";
  246.  
  247. button.addEventListener("click", function () {
  248. addNewTactic().catch(console.error);
  249. });
  250.  
  251. return button;
  252. }
  253.  
  254. async function addNewTactic() {
  255. let dropdown = document.getElementById("tacticsDropdown");
  256.  
  257. let outfieldPlayers = Array.from(
  258. document.querySelectorAll(outfieldPlayersSelector)
  259. );
  260. if (!validateTacticPlayerCount(outfieldPlayers)) {
  261. return;
  262. }
  263.  
  264. const tacticName = prompt("Please enter a name for the tactic: ");
  265. const isValidName = await validateTacticName(tacticName);
  266. if (!isValidName) {
  267. return;
  268. }
  269.  
  270. let coordinates = outfieldPlayers.map((player) => [
  271. parseInt(player.style.left),
  272. parseInt(player.style.top),
  273. ]);
  274.  
  275. let tactic = {
  276. name: tacticName,
  277. coordinates,
  278. id: generateUniqueId(),
  279. };
  280.  
  281. saveTacticToStorage(tactic).catch(console.error);
  282. addTacticsToDropdown(dropdown, [tactic]);
  283. dropdownTactics.push(tactic);
  284.  
  285. dropdown.value = tactic.name;
  286. handleTacticSelection(tactic.name);
  287.  
  288. alert("A new tactic has been added.");
  289. }
  290.  
  291. function validateTacticPlayerCount(outfieldPlayers) {
  292. let isGoalkeeper = document.querySelector(
  293. ".fieldpos.fieldpos-ok.goalkeeper.ui-draggable"
  294. );
  295.  
  296. outfieldPlayers = outfieldPlayers.filter(
  297. (player) => !player.classList.contains("fieldpos-collision")
  298. );
  299.  
  300. if (outfieldPlayers.length < 10 || !isGoalkeeper) {
  301. alert(
  302. "Error: invalid tactic. You must have 1 goalkeeper and 10 outfield players in valid positions."
  303. );
  304. return false;
  305. }
  306.  
  307. return true;
  308. }
  309.  
  310. async function validateTacticName(name) {
  311. if (!name) {
  312. alert("Error: you must provide a name for the tactic.");
  313. return false;
  314. }
  315.  
  316. const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
  317. if (tacticsData.tactics.some((t) => t.name === name)) {
  318. alert(
  319. "Error: a tactic with this name already exists. Please choose a different name."
  320. );
  321. return false;
  322. }
  323.  
  324. if (name.length > 50) {
  325. alert("Error: tactic name must be less than 50 characters.");
  326. return false;
  327. }
  328.  
  329. return true;
  330. }
  331.  
  332. async function saveTacticToStorage(tactic) {
  333. const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
  334. tacticsData.tactics.push(tactic);
  335. await GM_setValue("ls_tactics", tacticsData);
  336. }
  337.  
  338. // _____Delete tactic_____
  339.  
  340. function createDeleteTacticButton() {
  341. const button = document.createElement("button");
  342. button.id = "deleteTacticButton";
  343. button.textContent = "Delete tactic";
  344. button.style.fontFamily = "Montserrat, sans-serif";
  345. button.style.fontSize = "12px";
  346. button.style.color = "#000";
  347. button.style.marginLeft = "6px";
  348. button.style.cursor = "pointer";
  349.  
  350. button.addEventListener("click", function () {
  351. deleteTactic().catch(console.error);
  352. });
  353.  
  354. return button;
  355. }
  356.  
  357. async function deleteTactic() {
  358. let dropdown = document.getElementById("tacticsDropdown");
  359. let selectedTactic = dropdownTactics.find(
  360. (tactic) => tactic.name === dropdown.value
  361. );
  362.  
  363. if (!selectedTactic) {
  364. alert("Error: no tactic selected.");
  365. return;
  366. }
  367.  
  368. const confirmed = confirm(
  369. `Are you sure you want to delete the tactic "${selectedTactic.name}"?`
  370. );
  371.  
  372. if (!confirmed) {
  373. return;
  374. }
  375.  
  376. alert(`Tactic "${selectedTactic.name}" was successfully deleted!`);
  377.  
  378. const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
  379. tacticsData.tactics = tacticsData.tactics.filter(
  380. (tactic) => tactic.id !== selectedTactic.id
  381. );
  382.  
  383. await GM_setValue("ls_tactics", tacticsData);
  384.  
  385. dropdownTactics = dropdownTactics.filter(
  386. (tactic) => tactic.id !== selectedTactic.id
  387. );
  388.  
  389. const selectedOption = Array.from(dropdown.options).find(
  390. (option) => option.value === selectedTactic.name
  391. );
  392. dropdown.remove(selectedOption.index);
  393.  
  394. if (dropdown.options[0]?.disabled) {
  395. dropdown.selectedIndex = 0;
  396. }
  397. }
  398.  
  399. // _____Rename tactic_____
  400.  
  401. function createRenameTacticButton() {
  402. const button = document.createElement("button");
  403. button.id = "renameTacticButton";
  404. button.textContent = "Rename tactic";
  405. button.style.fontFamily = "Montserrat, sans-serif";
  406. button.style.fontSize = "12px";
  407. button.style.color = "#000";
  408. button.style.marginLeft = "6px";
  409. button.style.cursor = "pointer";
  410.  
  411. button.addEventListener("click", function () {
  412. renameTactic().catch(console.error);
  413. });
  414.  
  415. return button;
  416. }
  417.  
  418. async function renameTactic() {
  419. let dropdown = document.getElementById("tacticsDropdown");
  420. let selectedTactic = dropdownTactics.find(
  421. (tactic) => tactic.name === dropdown.value
  422. );
  423.  
  424. if (!selectedTactic) {
  425. alert("Error: no tactic selected.");
  426. return;
  427. }
  428.  
  429. const newName = prompt("Please enter a new name for this tactic: ");
  430. const isValidName = await validateTacticName(newName);
  431. if (!isValidName) {
  432. return;
  433. }
  434.  
  435. const selectedOption = Array.from(dropdown.options).find(
  436. (option) => option.value === selectedTactic.name
  437. );
  438.  
  439. const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
  440. tacticsData.tactics = tacticsData.tactics.map((tactic) => {
  441. if (tactic.id === selectedTactic.id) {
  442. tactic.name = newName;
  443. }
  444. return tactic;
  445. });
  446.  
  447. await GM_setValue("ls_tactics", tacticsData);
  448.  
  449. dropdownTactics = dropdownTactics.map((tactic) => {
  450. if (tactic.id === selectedTactic.id) {
  451. tactic.name = newName;
  452. }
  453. return tactic;
  454. });
  455.  
  456. selectedOption.value = newName;
  457. selectedOption.textContent = newName;
  458.  
  459. alert("Tactic was successfully renamed!");
  460. }
  461.  
  462. // _____Update tactic_____
  463.  
  464. function createUpdateTacticButton() {
  465. const button = document.createElement("button");
  466. button.id = "updateTacticButton";
  467. button.textContent = "Update tactic";
  468. button.style.fontFamily = "Montserrat, sans-serif";
  469. button.style.fontSize = "12px";
  470. button.style.color = "#000";
  471. button.style.marginLeft = "6px";
  472. button.style.cursor = "pointer";
  473.  
  474. button.addEventListener("click", function () {
  475. updateTactic().catch(console.error);
  476. });
  477.  
  478. return button;
  479. }
  480.  
  481. async function updateTactic() {
  482. let dropdown = document.getElementById("tacticsDropdown");
  483. let outfieldPlayers = Array.from(
  484. document.querySelectorAll(outfieldPlayersSelector)
  485. );
  486.  
  487. let selectedTactic = dropdownTactics.find(
  488. (tactic) => tactic.name === dropdown.value
  489. );
  490.  
  491. if (!selectedTactic) {
  492. alert("Error: no tactic selected.");
  493. return;
  494. }
  495.  
  496. const confirmed = confirm(
  497. `Are you sure you want to update "${selectedTactic.name}" coordinates?`
  498. );
  499.  
  500. if (!confirmed) {
  501. return;
  502. }
  503.  
  504. alert(
  505. `Tactic "${selectedTactic.name}" coordinates were successfully updated!`
  506. );
  507.  
  508. let updatedCoordinates = outfieldPlayers.map((player) => [
  509. parseInt(player.style.left),
  510. parseInt(player.style.top),
  511. ]);
  512.  
  513. const tacticsData = (await GM_getValue("ls_tactics")) || { tactics: [] };
  514.  
  515. for (let tactic of tacticsData.tactics) {
  516. if (tactic.id === selectedTactic.id) {
  517. tactic.coordinates = updatedCoordinates;
  518. }
  519. }
  520.  
  521. for (let tactic of dropdownTactics) {
  522. if (tactic.id === selectedTactic.id) {
  523. tactic.coordinates = updatedCoordinates;
  524. }
  525. }
  526.  
  527. await GM_setValue("ls_tactics", tacticsData);
  528. }
  529.  
  530. // _____Clear tactics_____
  531.  
  532. function createClearTacticsButton() {
  533. const button = document.createElement("button");
  534. button.id = "clearButton";
  535. button.textContent = "Clear tactics";
  536. button.style.fontFamily = "Montserrat, sans-serif";
  537. button.style.fontSize = "12px";
  538. button.style.color = "#000";
  539. button.style.marginLeft = "6px";
  540. button.style.cursor = "pointer";
  541.  
  542. button.addEventListener("click", function () {
  543. clearTactics().catch(console.error);
  544. });
  545.  
  546. return button;
  547. }
  548.  
  549. async function clearTactics() {
  550. const confirmed = confirm(
  551. "Are you sure you want to clear all tactics? This action will delete all saved tactics and cannot be undone."
  552. );
  553.  
  554. if (!confirmed) {
  555. return;
  556. }
  557.  
  558. await GM_setValue("ls_tactics", { tactics: [] });
  559. dropdownTactics = [];
  560.  
  561. const dropdown = document.getElementById("tacticsDropdown");
  562. dropdown.innerHTML = "";
  563. dropdown.disabled = true;
  564.  
  565. alert("Tactics successfully cleared!");
  566. }
  567.  
  568. // _____Reset default settings_____
  569.  
  570. function createResetTacticsButton() {
  571. const button = document.createElement("button");
  572. button.id = "resetButton";
  573. button.textContent = "Reset tactics";
  574. button.style.fontFamily = "Montserrat, sans-serif";
  575. button.style.fontSize = "12px";
  576. button.style.color = "#000";
  577. button.style.marginLeft = "6px";
  578. button.style.cursor = "pointer";
  579.  
  580. button.addEventListener("click", function () {
  581. resetTactics().catch(console.error);
  582. });
  583.  
  584. return button;
  585. }
  586.  
  587. async function resetTactics() {
  588. const confirmed = confirm(
  589. "Are you sure you want to reset? This action will overwrite all saved tactics and cannot be undone."
  590. );
  591.  
  592. if (!confirmed) {
  593. return;
  594. }
  595.  
  596. const response = await fetch(defaultTacticsDataUrl);
  597. const data = await response.json();
  598. const defaultTactics = data.tactics;
  599.  
  600. await GM_setValue("ls_tactics", { tactics: defaultTactics });
  601. dropdownTactics = defaultTactics;
  602.  
  603. const dropdown = document.getElementById("tacticsDropdown");
  604. dropdown.innerHTML = "";
  605. dropdown.appendChild(createPlaceholderOption());
  606. addTacticsToDropdown(dropdown, dropdownTactics);
  607. dropdown.disabled = false;
  608.  
  609. alert("Reset done!");
  610. }
  611.  
  612. // _____Import/Export_____
  613.  
  614. function createImportTacticsButton() {
  615. const button = document.createElement("button");
  616. button.id = "importButton";
  617. button.textContent = "Import tactics";
  618. button.style.fontFamily = "Montserrat, sans-serif";
  619. button.style.fontSize = "12px";
  620. button.style.color = "#000";
  621. button.style.marginLeft = "6px";
  622. button.style.cursor = "pointer";
  623.  
  624. button.addEventListener("click", function () {
  625. importTactics().catch(console.error);
  626. });
  627.  
  628. return button;
  629. }
  630.  
  631. function createExportTacticsButton() {
  632. const button = document.createElement("button");
  633. button.id = "exportButton";
  634. button.textContent = "Export tactics";
  635. button.style.fontFamily = "Montserrat, sans-serif";
  636. button.style.fontSize = "12px";
  637. button.style.color = "#000";
  638. button.style.marginLeft = "6px";
  639. button.style.cursor = "pointer";
  640. button.addEventListener("click", exportTactics);
  641. return button;
  642. }
  643.  
  644. async function importTactics() {
  645. const input = document.createElement("input");
  646. input.type = "file";
  647. input.accept = ".json";
  648.  
  649. input.onchange = async function (event) {
  650. const file = event.target.files[0];
  651. const reader = new FileReader();
  652.  
  653. reader.onload = async function (event) {
  654. const tactics = JSON.parse(event.target.result);
  655. await GM_setValue("ls_tactics", tactics);
  656.  
  657. dropdownTactics = tactics.tactics.sort((a, b) =>
  658. a.name.localeCompare(b.name)
  659. );
  660.  
  661. const dropdown = document.getElementById("tacticsDropdown");
  662. dropdown.innerHTML = "";
  663. dropdown.append(createPlaceholderOption());
  664. addTacticsToDropdown(dropdown, dropdownTactics);
  665. dropdown.disabled = false;
  666. };
  667.  
  668. reader.readAsText(file);
  669. };
  670.  
  671. input.click();
  672. }
  673.  
  674. function exportTactics() {
  675. const tactics = GM_getValue("ls_tactics", { tactics: [] });
  676. const tacticsJson = JSON.stringify(tactics);
  677. const blob = new Blob([tacticsJson], { type: "application/json" });
  678. const url = URL.createObjectURL(blob);
  679.  
  680. const link = document.createElement("a");
  681. link.href = url;
  682. link.download = "tactics.json";
  683. link.click();
  684.  
  685. URL.revokeObjectURL(url);
  686. }
  687.  
  688. // _____About button_____
  689.  
  690. function createAboutButton() {
  691. const button = document.createElement("button");
  692. button.id = "aboutButton";
  693. button.textContent = "About";
  694. button.style.fontFamily = "Montserrat, sans-serif";
  695. button.style.fontSize = "12px";
  696. button.style.color = "#000";
  697. button.style.marginLeft = "6px";
  698. button.style.cursor = "pointer";
  699.  
  700. button.addEventListener("click", function (event) {
  701. event.stopPropagation();
  702. if (modal.style.display === "none" || modal.style.opacity === "0") {
  703. showInfo();
  704. }
  705. });
  706.  
  707. return button;
  708. }
  709.  
  710. function showInfo() {
  711. modal.style.display = "block";
  712. setTimeout(function () {
  713. modal.style.opacity = "1";
  714. }, 0);
  715. }
  716.  
  717. function hideInfo() {
  718. modal.style.opacity = "0";
  719. setTimeout(function () {
  720. modal.style.display = "none";
  721. }, 500);
  722. }
  723.  
  724. function createInfoModal() {
  725. const modal = document.createElement("div");
  726. setupInfoModal(modal);
  727.  
  728. const modalContent = createModalContent();
  729. modal.appendChild(modalContent);
  730.  
  731. window.onclick = function (event) {
  732. if (event.target == modal) {
  733. hideInfo();
  734. }
  735. };
  736.  
  737. return modal;
  738. }
  739.  
  740. function setupInfoModal(modal) {
  741. modal.id = "infoModal";
  742. modal.style.display = "none";
  743. modal.style.position = "fixed";
  744. modal.style.zIndex = "1";
  745. modal.style.left = "50%";
  746. modal.style.top = "50%";
  747. modal.style.transform = "translate(-50%, -50%)";
  748. modal.style.opacity = "0";
  749. modal.style.transition = "opacity 0.5s ease-in-out";
  750. }
  751.  
  752. function createModalContent() {
  753. const modalContent = document.createElement("div");
  754. styleModalContent(modalContent);
  755.  
  756. const title = createTitle();
  757. const infoText = createInfoText();
  758. const feedbackText = createFeedbackText();
  759.  
  760. modalContent.appendChild(title);
  761. modalContent.appendChild(infoText);
  762. modalContent.appendChild(feedbackText);
  763.  
  764. return modalContent;
  765. }
  766.  
  767. function styleModalContent(content) {
  768. content.style.backgroundColor = "#fefefe";
  769. content.style.margin = "auto";
  770. content.style.padding = "20px";
  771. content.style.border = "1px solid #888";
  772. content.style.width = "80%";
  773. content.style.maxWidth = "500px";
  774. content.style.borderRadius = "10px";
  775. content.style.fontFamily = "Montserrat, sans-serif";
  776. content.style.textAlign = "center";
  777. content.style.color = "#000";
  778. content.style.fontSize = "16px";
  779. content.style.lineHeight = "1.5";
  780. }
  781.  
  782. function createTitle() {
  783. const title = document.createElement("h2");
  784. title.textContent = "MZ Tactics Selector";
  785. title.style.fontSize = "24px";
  786. title.style.fontWeight = "bold";
  787. title.style.marginBottom = "20px";
  788. return title;
  789. }
  790.  
  791. function createInfoText() {
  792. const infoText = document.createElement("p");
  793. infoText.innerHTML =
  794. 'For instructions, click <a href="https://greasyfork.org/pt-BR/scripts/467712-mz-tactics-selector" style="color: #007BFF;">here</a>.';
  795. return infoText;
  796. }
  797.  
  798. function createFeedbackText() {
  799. const feedbackText = document.createElement("p");
  800. feedbackText.innerHTML =
  801. 'If you run into any issues or have any suggestions, contact me here: <a href="https://www.managerzone.com/?p=guestbook&uid=8623925"><img src="https://www.managerzone.com/img/soccer/reply_guestbook.gif"></a>';
  802. return feedbackText;
  803. }
  804.  
  805. // _____Other_____
  806.  
  807. function appendChildren(element, children) {
  808. children.forEach((ch) => {
  809. element.appendChild(ch);
  810. });
  811. }
  812.  
  813. function insertAfterElement(toBeInserted, element) {
  814. element.parentNode.insertBefore(toBeInserted, element.nextSibling);
  815. }
  816.  
  817. function generateUniqueId() {
  818. let currentDate = new Date();
  819. return (
  820. currentDate.getFullYear() +
  821. "-" +
  822. (currentDate.getMonth() + 1) +
  823. "-" +
  824. currentDate.getDate() +
  825. "_" +
  826. currentDate.getHours() +
  827. "-" +
  828. currentDate.getMinutes() +
  829. "-" +
  830. currentDate.getSeconds() +
  831. "_" +
  832. Math.random().toString(36).substring(2, 15)
  833. );
  834. }
  835.  
  836. function isSoccerTacticsPage() {
  837. return document.getElementById("tactics_box").classList.contains("soccer");
  838. }
  839. })();