您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a scroll to parent comment button to nested comments when clicking the more (three dots) button on a nested comment, and a button to the parent comment to scroll back to that comment from the parent (also after clicking the parent comment more button).
当前为
// ==UserScript== // @name [Lemmy] Scroll to parent comment // @version 0.7 // @license GPL-3.0 // @description Adds a scroll to parent comment button to nested comments when clicking the more (three dots) button on a nested comment, and a button to the parent comment to scroll back to that comment from the parent (also after clicking the parent comment more button). // @author blackvoid // @match <your instance hostname>/* (e.g. https://lemmy.world/*) // @grant none // @namespace https://greasyfork.org/users/1149746 // ==/UserScript== (function () { "use strict"; // The SVG path for the reply icon that is used also for the go to parent // and the go back to child buttons that this script adds. const path = '<path d="M19 16.685c0 0-2.225-9.732-11-9.732v-3.984l-7 6.573 7 6.69v-4.357c4.763-0.001 8.516 0.421 11 4.81z"></path>'; // Creates the button with an icon, depending on the type (go to parent, // go back to child) function createButton(type) { let label, rotate; // We reuse the reply button icon for our new icons if (type === "parent") { rotate = "70deg"; label = "parent"; } else { rotate = "-70deg"; label = "back to child"; } const node = document.createElement("button"); node.classList = `btn btn-link btn-animate text-muted`; // Content for the on hover tooltip. // Doesn't always work for the back to child button since tippy // is called only on pressing the more button. // If you clicked more on the parent before, there will be no tooltip // on the newly added back to child button. node.setAttribute("data-tippy-content", label); node.setAttribute("aria-label", label); node.innerHTML = `<svg viewBox="0 0 20 20" style="transform: rotateZ(${rotate});" class="icon icon-inline">${path}<div class="visually-hidden"><title>parent</title></div></svg></button>`; return node; } // Scroll back to the child comment with a button that appears in the list of // more controls if go to parent button was clicked. function addBackButton(node) { const moreButton = node.querySelector(".btn-more"); const button = createButton("child"); // Scroll back to the child comment on click and remove the button button.addEventListener("click", () => { node.childComment.scrollIntoView(); button.remove(); node.removeAttribute("data-has-back-button"); }); if (moreButton) { // The attribute prevents adding multiple back to child buttons if (node.getAttribute("data-has-back-button")) return; node.setAttribute("data-has-back-button", 1); // Make it appear on clicking the more (dots) button moreButton.addEventListener("click", () => { appendToMoreControls(moreButton, button); }); } else { // If it was already clicked (and therefore disappeared) const controls = node.querySelector("div:nth-of-type(3)"); const oldButton = node.querySelector(".go-to-child"); if (oldButton) { controls.replaceChild(button, oldButton); } else { controls.appendChild(button); } } } // Append the button to the list of additional controls on a comment, // after clicking the more (dots) button function appendToMoreControls(moreButton, button) { moreButton.parentNode.appendChild(button); } // Observes the whole document because lemmy-ui is a SPA and once // the document is loaded, it never reloads on navigation const html = document.querySelector("html"); const mutationObserver = new MutationObserver(appendGoToParent); mutationObserver.observe(html, { childList: true, subtree: true }); // Keep track of visited nodes. Probably slower when only processing // addedNodes from mutation record, but much less complex. const visited = new WeakSet(); // Invoke the observer handler immediately // for posts opened via a deep link (SSRed) appendGoToParent(); function appendGoToParent() { // The more (dots) buttons that we're going to add click listeners to const moreButtons = document.querySelectorAll( "div .comment .comment .btn-more" ); // Process the more buttons - add click listener and attach the Parent buttons Array.from(moreButtons).map(moreButton => { // Do not attach clicks to a comment more than once if (visited.has(moreButton)) return; // Add the element into the set of visited nodes visited.add(moreButton); // Get the parent node, 6 levels up from the child's more button, // so we can later scroll to it if the Parent button is pressed let parentComment = moreButton; Array(6) .fill(true) .map(() => { parentComment = parentComment.parentNode; }); parentComment = parentComment.children[0]; // Listen to clicks on the more (dots) button moreButton.addEventListener("click", () => { // This comment to be scrolled back to from the parent // when clicking the back to child button const thisComment = moreButton.parentNode.parentNode; // Create and append the parent button to the list of additional // controls that appear upon clicking the dots button const node = createButton("parent"); node.addEventListener("click", () => { parentComment.scrollIntoView(); parentComment.childComment = thisComment; // Also add the back to child button addBackButton(parentComment); }); appendToMoreControls(moreButton, node); }); }); } })();