您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds vertical bars to the left of the comments, enabling you to easily collapse the parent comments. It also can leave only a specified number of comments expanded and auto-collapse the rest.
当前为
// ==UserScript== // @name Collapse HackerNews Parent Comments // @description Adds vertical bars to the left of the comments, enabling you to easily collapse the parent comments. It also can leave only a specified number of comments expanded and auto-collapse the rest. // @author BLBC (github.com/hjk789, greasyfork.org/users/679182-hjk789) // @copyright 2020+, BLBC (github.com/hjk789, greasyfork.org/users/679182-hjk789) // @version 1.2.5 // @homepage https://github.com/hjk789/Userscripts/tree/master/Collapse-HackerNews-Parent-Comments // @license https://github.com/hjk789/Userscripts/tree/master/Collapse-HackerNews-Parent-Comments#license // @grant none // @include https://news.ycombinator.com/item* // @namespace https://greasyfork.org/users/679182 // ==/UserScript== //--------------- Settings ----------------- const autoCollapse = false // Whether all comments, other than the number of comments below, should be auto-collapsed. // If set to false, all comments will be left expanded and the settings below have no effect. const numberOfRoots = 5 const numberOfReplies = 3 const numberOfRepliesOfReplies = 1 //------------------------------------------ const fadeOnHoverStyle = document.createElement("style") fadeOnHoverStyle.innerHTML = ".verticalBar:hover { background-color: gray !important; }" document.body.appendChild(fadeOnHoverStyle) // HackerNews puts a 1x1 image before each comment and sets it's width according to each comment depth. Each level of depth adds 40px of width to this // image, starting from 0 which are the root comments. The ones with a 14px width are flagged comments and the "More comments" link. // This userscript was first created before HN implemented the root/parent/prev/next links, and at that time the layout didn't have any easier way of identifying // the hierarchy of the comments (it was just a list of comments pushed to the right), so that's the only way I had found to achieve this at that time. const spacingImgs = document.querySelectorAll(".ind img[height='1']:not([width='14'])") let root = 0 let i = spacingImgs.length-1 // It's required to loop backwards, otherwise the hidden comments reappear when collapsed. let commentHier = [] const collapseAll = setInterval(function() // An interval of 1ms is being used to prevent the page from freezing until it finishes. Also, it creates a cool effect when { // the comments are being collapsed. It does make it take a few more seconds to finish in comment-heavy posts (150+) though. let commentContainer = spacingImgs[i].parentElement.parentElement.parentElement.parentElement.parentElement.parentElement commentContainer.firstChild.style = "border-top: 5px transparent solid" // To visually separate each vertical bar. spacingImgs[i].parentElement.style = "position: relative" const clicky = commentContainer.querySelectorAll(".clicky:not(.togg)") // HN added a scrolling animation to the hierarchy links, which breaks the script. for (let i=0; i < clicky.length; i++) // The animation is only applied to elements with the class "clicky". clicky[i].className = clicky[i].className.replace("clicky","") // This removes the clicky class from every hierarchy link of the comment. if (autoCollapse && !commentContainer.classList.contains("coll")) // Collapse only if it's not collapsed yet. This is for signed-in users, as HN remembers which comments were collapsed. commentContainer.querySelector(".togg").click() i-- if (i == -1) // When finished collapsing all comments, now it's time to add the bars. { clearInterval(collapseAll) for (i=0; i < spacingImgs.length; i++) { const level = spacingImgs[i].width / 40 commentContainer = spacingImgs[i].parentElement.parentElement.parentElement.parentElement.parentElement.parentElement const commentToggle = commentContainer.querySelector(".togg") // Store the current hierarchy in an array commentHier[level] = commentToggle let divs = [] for (let j = spacingImgs[i].width; j >= 0; j -= 40) // Start adding the vertical bar from the current depth and go backwards. { // Create the vertical bar const div = document.createElement("div") div.className = "verticalBar" div.commentHier = commentHier[j/40] // Store in an attribute of the element this comment's parent respective to the level of the vertical bar, for easy access. div.onclick = function(e) { e.target.commentHier.click() // When a vertical bar is clicked, collapse the respective parent comment. // Click the "next" link of the parent comment when it's out of view. if (e.target.commentHier.getBoundingClientRect().y < 0) e.target.commentHier.previousElementSibling.lastChild.click() } let style = "left: " + (-5 + j) + "px; width: 12px; background-color: lightgray; position: absolute; z-index: 99; transition: 0.15s; " // Make it so that the vertical bars are only separated when followed by comments of same level of depth if (j == spacingImgs[i].width && spacingImgs[i-1] != null && spacingImgs[i].width <= spacingImgs[i-1].width) style += "top: 5px; height: calc(100% + 8px); " else style += "top: 0px; height: calc(100% + 13px); " div.style = style divs.push(div) } for (let j = divs.length - 1; j >= 0; j--) spacingImgs[i].parentElement.appendChild(divs[j]) } if (autoCollapse) // When finished collapsing and adding the vertical bars to all comments, now it's time to expand only a few of the first comments. { let sub40, sub80 for (i=0; i < spacingImgs.length; i++) { commentToggle = spacingImgs[i].parentElement.parentElement.querySelector(".togg") if (spacingImgs[i].width == 0) // If it's a root comment. { root++ if (root == numberOfRoots + 1) // If there's already <numberOfRoots> comments expanded, then stop expanding. break commentToggle.click() sub40 = 0 sub80 = 0 } else if (spacingImgs[i].width == 40 && sub40 < numberOfReplies) // If it's a reply to the root comment, only expand up to <numberOfReplies>. { commentToggle.click() sub40++ sub80 = 0 } else if (spacingImgs[i].width == 80 && sub80 < numberOfRepliesOfReplies) // If it's a reply to the reply, only expand up to <numberOfRepliesOfReplies>. { commentToggle.click() sub80++ } } } } }, 1)