Automatically and smoothly expands all collapsed comments on Reddit [except for permalink ones...] with enhanced performance
当前为
// ==UserScript==
// @name Reddit Comment Auto-Expander (Smooth):
// @namespace _pc
// @author verydelight
// @version 0.91
// @license MIT
// @compatible Firefox Tampermonkey
// @description Automatically and smoothly expands all collapsed comments on Reddit [except for permalink ones...] with enhanced performance
// @match *://*.reddit.com/r/*/comments/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
const pre_load = 1200;
const batch_size = 12;
function safeClick(el) {
if (!el || el.disabled || el.offsetParent === null) return;
const event = new MouseEvent('click', { bubbles: true, cancelable: true });
el.dispatchEvent(event);
}
function isInViewport(el) {
const rect = el.getBoundingClientRect();
return rect.top < window.innerHeight + pre_load && rect.bottom > -pre_load;
}
function expandVisible() {
const batch = [];
const editor = document.querySelector('[data-test-id="post-content"], [data-testid="comment"]');
document.querySelectorAll('shreddit-comment button[aria-controls][aria-expanded="false"], shreddit-comment button[rpl]:not([aria-expanded="true"])')
.forEach(btn => {
if (btn.closest('aside')) return;
if (editor && editor.contains(btn)) return;
if (isInViewport(btn) && !btn.closest('shreddit-comment-action-row')) batch.push(btn);
});
document.querySelectorAll('faceplate-partial button')
.forEach(btn => {
if (btn.closest('aside')) return;
if (editor && editor.contains(btn)) return;
if (isInViewport(btn) && !btn.closest('shreddit-comment-action-row') && btn.offsetParent !== null) batch.push(btn);
});
document.querySelectorAll('shreddit-comment[collapsed]')
.forEach(comment => {
if (comment.closest('aside')) return;
if (editor && editor.contains(comment)) return;
if (!isInViewport(comment)) return;
const btn = comment.querySelector('button[aria-controls]');
if (btn && btn.getAttribute('aria-expanded') === 'false') batch.push(btn);
else if (!btn) batch.push(comment);
});
for (let i = 0; i < batch.length; i += batch_size) {
setTimeout(() => {
batch.slice(i, i + batch_size).forEach(el => {
safeClick(el);
if (el.matches('shreddit-comment[collapsed]') && !el.querySelector('button[aria-controls]')) {
el.removeAttribute('collapsed');
el.querySelectorAll('[slot^="children"], [slot="next-reply"]').forEach(child => {
child.hidden = false;
child.style.display = '';
});
}
});
}, i * 15);
}
}
const observer = new MutationObserver(mutations => {
mutations.forEach(m => {
if (m.type === 'childList' && m.addedNodes.length > 0) {
expandVisible();
}
});
});
function initObserver() {
const container = document.querySelector('shreddit-comments') ||
document.querySelector('[data-test-id="comments-page"], [data-testid="comments-page"]') ||
document.querySelector('shreddit-comment')?.closest('main, #SHORTCUT_FOCUSABLE_DIV, body');
if (!container) {
setTimeout(initObserver, 250);
return;
}
observer.observe(container, { childList: true, subtree: true });
expandVisible();
}
initObserver();
window.addEventListener('scroll', () => expandVisible());
})();