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.2.2
// @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 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);
// 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 = messageTopLinks[2].href;
const date = messageTopLinks[1].querySelector('.desktop-only').innerText;
const messagePermalink = messageTopLinks[1].href;
if(lastQuotedMsg !== null && replyBox.value.length) {
replyBox.value += `\n\n`;
} else if(replyBox.value.length) {
replyBox.value += `\n`;
}
replyBox.value += `> From: [${username}](${filteredThreadPermalink}) at [${date}](${messagePermalink})`;
lastQuotedMsg = messagePermalink;
};
// 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 = messageTopLinks[1].href;
console.log('lastQuotedMsg', lastQuotedMsg);
console.log('messagePermalink', messagePermalink);
return lastQuotedMsg === messagePermalink
};
// 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);
}
}
}
}
})();