您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Alt + Click on one or more images in a post to quote them.
// ==UserScript== // @name Quote specific images in a post. // @author Joshh // @namespace https://tljoshh.com // @version 0.3 // @description Alt + Click on one or more images in a post to quote them. // @match *://*.websight.blue/thread/* // @icon https://www.google.com/s2/favicons?sz=64&domain=websight.blue // @license MIT // ==/UserScript== (function() { 'use strict'; let lastQuotedMsg = null; const form = document.querySelector('#reply-form'); const replyBox = document.querySelector('#reply-content'); const postsContainer = document.querySelector('#messages'); const posts = document.querySelectorAll('.post'); // Listen to all for an alt+click event for (const post of posts) { post.addEventListener('click', handleClick); }; // Listen for new posts added by livelinks startMutationObserver(postsContainer); // Clear last quoted message upon submission of new post form.addEventListener('submit', handlePostSubmission); // Remove the last quoted msg id function handlePostSubmission() { lastQuotedMsg = null; } // Target event: alt+click on images in a post function handleClick(e) { const { altKey, target, currentTarget } = e; if (altKey && target.tagName === 'IMG') { e.preventDefault(); handleImageClick(currentTarget, target); } }; // Add the markdown formatted text for the quoted message identifier and the image to the reply textarea function handleImageClick(post, image) { // Append quoted message identifier const authorBoxNotAdded = !checkIfAuthorBoxAdded(post); if(authorBoxNotAdded) { addAuthorBox(post); } // Append quoted image to replybox addQuotedImage(image); } // Add an image to the reply textarea function addQuotedImage(img) { const { alt, src } = img; replyBox.value += `\n> `; }; // Add quoted message identifier to reply textarea and store the permalink id function addAuthorBox(post) { const username = post.querySelector('.post-author').innerText; const messageTopLinks = post.querySelectorAll('.message-top > a'); const filteredThreadPermalink = new URL(messageTopLinks[2].href); const filteredThreadPermalinkTokens = filteredThreadPermalink.pathname.split('/'); const date = messageTopLinks[1].querySelector('.desktop-only').innerText; const messagePermalink = new URL(messageTopLinks[1].href); if(lastQuotedMsg !== null && replyBox.value.length) { replyBox.value += `\n\n`; } else if(replyBox.value.length) { replyBox.value += `\n`; } const messagePermalinkTokens = messagePermalink.pathname.split('/'); replyBox.value += `> From: [${username}](${filteredThreadPermalink.pathname}) at [${date}](/thread/${messagePermalinkTokens[2]}#msg-${filteredThreadPermalinkTokens[3]})\n>`; lastQuotedMsg = messagePermalink.pathname; }; // Check what the last quoted message identifier was and determine if we need to add an author box. function checkIfAuthorBoxAdded(post) { const messageTopLinks = post.querySelectorAll('.message-top > a'); const messagePermalink = new URL(messageTopLinks[1].href); return lastQuotedMsg === messagePermalink.pathname; }; // Add event listener to any posts added to DOM via livelinks function startMutationObserver(targetNode) { // Options for the observer (which mutations to observe) const config = { childList: true }; // Callback function to execute when mutations are observed const callback = (mutationList, observer) => { // For all mutations made to the target node, check if any nodes were added... for (const mutation of mutationList) { handleMutation(mutation); } }; // Create an observer instance linked to the callback function const observer = new MutationObserver(callback); // Start observing the target node for configured mutations observer.observe(targetNode, config); } // Handle any changes made to the messages container. function handleMutation(mutation) { // For all nodes that were added, check if any where posts made by a user and add a click event listener. if(mutation.addedNodes.length) { for (const addedNode of mutation.addedNodes) { if (!addedNode.tagName) continue; // Not an element if(addedNode.classList.contains('post')) { addedNode.addEventListener('click', handleClick); } } } } })();