NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name AntiGameReborn SpyTableGrouper // @namespace https://openuserjs.org/users/MisatoTremor // @version 1.1.0 // @description Groups the AntiGameReborn SpyTable by galaxy // @author MisatoTremor // @license MIT // @copyright 2024, MisatoTremor // @match https://*.ogame.gameforge.com/game/index.php?page=ingame&component=messages* // @updateURL https://openuserjs.org/meta/MisatoTremor/AntiGameReborn_SpyTableGrouper.meta.js // @downloadURL https://openuserjs.org/install/MisatoTremor/AntiGameReborn_SpyTableGrouper.user.js // @grant GM_addStyle // @run-at document-start // ==/UserScript== 'use strict'; // #region class SpyTableGrouper { constructor() { this.observerQueue = {}; this.mutationList = {}; this.observerTimers = []; this.observer = new MutationObserver(mutations => { (() => { let now = performance.now(); for(let i=0, len=mutations.length; i<len; i++) { let mutation = mutations[i]; if('agoSpyReportOverview' == mutation.target.id) { this.mutationList.tablereport = now; } } })(); if(Object.keys(this.mutationList).length > 0) tryUpdate(); }); let tryUpdate = () => { Object.keys(this.mutationList).forEach(k => { if(typeof this.observerQueue[k] === 'function') this.observerQueue[k](); delete this.mutationList[k]; }); } this.observer.observe(document.querySelector(".messageContent"), {childList:true, subtree:true}); this.observeMutation(() => this.groupTable(), 'tablereport'); } groupTable() { const table = document.querySelector("#agoSpyReportOverview .ago_reports"); if (table && !table.classList.contains("grouped")) { // Get all the rows of the table const tableBody = table.querySelector("tbody"); const tableRows = Array.from(table.querySelectorAll("tbody tr")); // Sort the rows based on their x-coordinate values tableRows.sort((row1, row2) => { const x1 = parseFloat(row1.cells[0].textContent); const x2 = parseFloat(row2.cells[0].textContent); return x1 - x2; }); tableBody.remove(); // Create an empty tbody for the first group let currentGroup = document.createElement("tbody"); // Iterate over the sorted rows and group them tableRows.forEach((row) => { const x = parseFloat(row.cells[0].textContent); if (x !== parseFloat(currentGroup.id)) { // If the x-coordinate of the current row is different from the current group, // create a new tbody and append the current group to the table currentGroup = document.createElement("tbody"); currentGroup.id = x; table.appendChild(currentGroup); } row.classList.remove("even") // Append the current row to the current group currentGroup.appendChild(row); }); table.classList.add("grouped"); } } observeMutation(callback, id) { this.observerQueue[id] = callback; } } class Util { static createDom(element, params, content) { params = params || {}; content = content ?? ''; let dom = document.createElement(element); Object.entries(params).forEach(p => dom.setAttribute(p[0], p[1])); dom.innerHTML = content; return dom; } } // #endregion if(document.readyState !== 'loading') { unsafeWindow.agr_stg = new SpyTableGrouper(); } else { window.addEventListener("DOMContentLoaded", () => { unsafeWindow.agr_stg = new SpyTableGrouper(); }); } // #region const css = ` /*css*/ #agoSpyReportOverview .ago_reports tbody:not(:last-of-type)::after { content: ''; display: block; height: 1rem; } #agoSpyReportOverview .ago_reports tbody tr:nth-child(even) { background-color: #0f141a; } /*!css*/ `; GM_addStyle(css); // #endregion