// ==UserScript== // @name GGn Group Expansion // @version 1.2 // @author SleepingGiant // @description Adds quick buttons for expanding all groups and filelist on GGn pages. // @namespace https://greasyfork.org/users/1395131 // @match https://gazellegames.net/torrents.php?id=* // @grant none // @downloadURL none // ==/UserScript== (function () { 'use strict'; function ensureVerticalCornerContainer() { let container = document.getElementById('vertical-corner-container'); if (!container) { container = document.createElement('div'); container.id = 'vertical-corner-container'; container.style.position = 'absolute'; // match Multi Reporter document.body.appendChild(container); const groupDetails = document.getElementById('content'); if (groupDetails) { container.style.left = (groupDetails.offsetLeft + groupDetails.offsetWidth) + 'px'; container.style.top = groupDetails.offsetTop + 'px'; } } return container; } function insertExpandAllButton() { const container = ensureVerticalCornerContainer(); const expandButton = document.createElement('button'); expandButton.textContent = 'Expand All'; expandButton.type = 'button'; expandButton.style.writingMode = 'vertical-lr'; expandButton.style.height = 'unset'; expandButton.style.margin = '4px 0'; expandButton.id = 'expand-all-button'; // so we can reference it later expandButton.onclick = () => { expandAll(); }; container.appendChild(expandButton); } function insertInlineEditionButtons() { const editions = document.querySelectorAll('.edition_info'); editions.forEach(edition => { const btn = document.createElement('button'); btn.textContent = 'Expand Edition'; btn.style.marginLeft = '10px'; btn.type = 'button'; btn.classList.add('expand-edition-button'); btn.onclick = (e) => { e.stopPropagation(); // Don't trigger edition row collapse toggle expandSingleEdition(edition); }; edition.appendChild(btn); }); } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function expandAll() { // Expand all editions document.querySelectorAll('.edition_info').forEach(edition => { const editionIdMatch = edition.getAttribute('onclick')?.match(/#edition_(\d+)/); if (editionIdMatch) { const tbody = document.getElementById(`edition_${editionIdMatch[1]}`); if (tbody && tbody.style.display === 'none') { edition.click(); } } }); document.querySelectorAll('a[onclick*="torrent_"]').forEach(a => { const torrentIdMatch = a.getAttribute('onclick')?.match(/#torrent_(\d+)/); if (torrentIdMatch) { const torrentId = torrentIdMatch[1]; const torrentRow = document.getElementById(`torrent_${torrentId}`); if (torrentRow && torrentRow.classList.contains('hidden')) { jQuery(`#torrent_${torrentId}`).toggle(); } } }); document.querySelectorAll('a[onclick^="show_files"]').forEach(a => { const fileId = a.getAttribute('onclick')?.match(/\d+/)?.[0]; if (fileId) { const filesDiv = document.getElementById(`files_${fileId}`); if (filesDiv && filesDiv.classList.contains('hidden')) { show_files(fileId); } } }); } function expandSingleEdition(edition) { const editionIdMatch = edition.getAttribute('onclick')?.match(/#edition_(\d+)/); if (editionIdMatch) { const editionId = editionIdMatch[1]; const tbody = document.getElementById(`edition_${editionId}`); if (tbody && tbody.style.display === 'none') { edition.click(); } if (tbody) { tbody.querySelectorAll('a[onclick*="torrent_"]').forEach(a => { const torrentIdMatch = a.getAttribute('onclick')?.match(/#torrent_(\d+)/); if (torrentIdMatch) { const torrentId = torrentIdMatch[1]; const torrentRow = document.getElementById(`torrent_${torrentId}`); if (torrentRow && torrentRow.classList.contains('hidden')) { jQuery(`#torrent_${torrentId}`).toggle(); } } }); tbody.querySelectorAll('a[onclick^="show_files"]').forEach(a => { const fileId = a.getAttribute('onclick')?.match(/\d+/)?.[0]; if (fileId) { const filesDiv = document.getElementById(`files_${fileId}`); if (filesDiv && filesDiv.classList.contains('hidden')) { show_files(fileId); } } }); } } } const loader = setInterval(() => { if (document.getElementById('expand-all-button') || document.querySelector('.expand-edition-button')) { clearInterval(loader); } else { insertExpandAllButton(); insertInlineEditionButtons(); } }, 200); })();