// ==UserScript== // @name 8chan Collapsible Thread Chains/Nested Inline Replies // @version 1.5.9 // @description Make quote links collapsible with indented hierarchy. Override panelBacklinks behavior. // @match https://8chan.moe/*/res/* // @match https://8chan.se/*/res/* // @grant GM_addStyle // @grant GM.addStyle // @license MIT // @namespace https://greasyfork.org/users/1459581 // @downloadURL none // ==/UserScript== (function() { 'use strict'; GM_addStyle(` .collapsible-container { margin-left: 20px; padding-left: 5px; margin-top: 8px; } .post-content.collapsed { display: none; } .altBacklinks { display: none !important; } .postCell.post-content { border: none !important; } .innerPost { border-top: 1px solid #474b53; border-left: 1px solid #474b53; width: auto; max-width: none !important; } `); const linkContainers = new WeakMap(); function handlequickreply(event) { const link = event.target.closest('a'); qr.showQr(link.href.match(/#q(\d+)/)[1]); } function handleQuoteClick(event) { event.preventDefault(); event.stopPropagation(); const link = event.target.closest('a'); if (!link) return; const rawHash = link.hash.includes('?') ? link.hash.split('?')[0] : link.hash; const targetId = rawHash.substring(1).replace(/^q/, ''); const targetPost = document.getElementById(targetId); if (!targetPost) return; let container = linkContainers.get(link); if (container) { const clone = container.querySelector('.post-content'); clone.classList.toggle('collapsed'); return; } const level = link.closest('.collapsible-container')?.dataset.level || 0; container = document.createElement('div'); container.className = 'collapsible-container'; container.dataset.level = parseInt(level) + 1; const clone = targetPost.cloneNode(true); clone.removeAttribute('id'); clone.classList.add('post-content'); processClonedElements(clone); container.appendChild(clone); const postContainer = link.closest('.innerPost'); if (postContainer) { postContainer.appendChild(container); } else { link.parentNode.insertBefore(container, link.nextSibling); } linkContainers.set(link, container); } function processClonedElements(clone) { clone.querySelectorAll('a.linkQuote, .panelBacklinks a').forEach(link => { const href = link.getAttribute('href'); if (href && href.includes('#')) { const cleanHash = href.split('#')[1].split('?')[0]; link.href = `#${cleanHash}`; } link.addEventListener('click', handleQuoteClick); }); const firstQuoteLink = clone.querySelector('a.linkQuote'); if (firstQuoteLink) { firstQuoteLink.addEventListener('click', handlequickreply); } } function initializeLinks() { document.querySelectorAll('a.linkQuote, .panelBacklinks a').forEach(link => { const href = link.getAttribute('href'); if (href?.includes('#')) { link.href = `#${href.split('#')[1].split('?')[0]}`; } link.removeEventListener('click', handleQuoteClick); link.addEventListener('click', handleQuoteClick); }); // Add the panelBacklinks prevention document.querySelectorAll('span.panelBacklinks a').forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); }); }); } initializeLinks(); new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length) { initializeLinks(); } }); }).observe(document.body, { childList: true, subtree: true }); })();