Greasy Fork is available in English.
Create a new button to ask ChatGPT explain Japanese text from clipboard. 创建一个按钮来让ChatGPT解释剪贴板中的日文。
// ==UserScript==
// @name ChatTranslate
// @namespace http://tampermonkey.net/
// @version 0.7
// @description Create a new button to ask ChatGPT explain Japanese text from clipboard. 创建一个按钮来让ChatGPT解释剪贴板中的日文。
// @author Glaceon
// @match https://chat.openai.com/*
// @grant none
// @license MIT
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// CSS for the button
const css = `
#buttonLoad {
border-radius: 10px; /* Rounded corners */
font-size: 16px; /* Font size */
border-color: lightgray;
padding: 10px 20px;
background: none;
position: absolute;
left: -290px;
display: flex;
border: 1px solid lightgrey;
}
.list-container ul {
counter-reset: list-counter; /* Initialize the counter */
list-style-type: none; /* Removes default list style */
}
.list-container li {
counter-increment: list-counter; /* Increment the counter */
margin-bottom: 8px; /* Add some bottom margin for spacing between items */
padding-left: 30px; /* Provide padding to avoid text overlap */
}
.list-container li::before {
content: counter(list-counter) ". "; /* Display the counter and a dot */
margin-left: -30px; /* Pull the number into the padding area */
text-align: right; /* Right-align the number within the negative margin space */
}
.language-select {
border-radius: 10px; /* Rounded corners */
font-size: 16px; /* Font size */
border-color: lightgray;
padding: 10px 20px;
background: none;
}
`;
// Inject CSS into the head
const style = document.createElement('style');
document.head.appendChild(style);
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
function insertDivs(listNode, htmlString) {
var parser = new DOMParser();
var doc = parser.parseFromString(htmlString, 'text/html');
var divs = doc.querySelectorAll('p');
console.log('hi');
console.log(divs);
divs.forEach(function(div) {
listNode.appendChild(div.cloneNode(true));
});
}
function askChat(text) {
// let newButton = document.querySelector('askButton');
// newButton.disabled = true;
let sendButton = document.querySelector('button[data-testid="send-button"]');
let textarea = document.getElementById('prompt-textarea');
let lang = document.getElementById('languageSelect');
// Successfully got text from clipboard
if (lang.value == 'JA') {
textarea.value = `
解释日文并注音. 例如:
解释: 翌日が訪れた.
意思是"第二天到了". 各部分解释如下:
翌日 (よくじつ): 这个词的意思是“次日”或者“第二天”,指的是在谈话的当天之后的那一天。
が訪れた (がおとずれた): 这里的“が”是一个语法上的连接词,用来连接主语和谓语。而“訪れた”是“訪れる”的过去式,意思是“到来”或者“访问”。
---
解释: `; // Set clipboard text to textarea
} else if (lang.value == 'EN') {
textarea.value = `Translate to English\n`;
} else {
textarea.value = `翻译为中文\n`;
}
textarea.value += text;
// Dispatch an 'input' event to mimic user typing
let event = new Event('input', {
bubbles: true,
cancelable: true,
});
textarea.dispatchEvent(event);
// Rest of your code to enable and click the send button...
let clickInterval = setInterval(function() {
if (!sendButton.disabled) { // Check if the button is not disabled
sendButton.click();
clearInterval(clickInterval); // Clear the interval to stop checking
// newButton.disabled = false;
}
}, 100);
}
function createSentenceLists() {
// let form = document.querySelector('form');
// let contents = document.createElement('div');
// contents.style = "overflow: auto; max-height:30vh";
// contents.className = "mx-auto md:px-5 lg:px-1 xl:px-5 md:max-w-2xl";
let contents = document.createElement("div");
// Set the id attribute of the new div to "tl"
contents.id = "tl";
// Apply CSS styles to position the div
contents.style.top = "0";
contents.style.right = "0";
contents.style.width = "25%";
contents.style.height = "100%";
contents.style.overflow_y = "auto";
contents.style.overflow = "auto";
// contents.style.backgroundColor = "lightgray";
contents.style.position = "fixed";
// Get a reference to the <main> element
// var presentationDiv = document.querySelector('div[role="presentation"]').firstElementChild;
// presentationDiv.style.display = "flex";
// form.parentNode.appendChild(contents);
// Append the new div to the <main> element
document.querySelector("main").appendChild(contents);
// Create a file input element
let file = document.createElement('input');
// Append file input to contents
contents.appendChild(file);
contents.classList = "list-container"
file.id = 'fileInput';
file.type = 'file'; // Specify that this is a file input
file.accept = '.html';
file.style.display = 'none'; // Hide the file input
file.addEventListener('change', function(event) {
if (file.files.length > 0) {
let reader = new FileReader();
reader.onload = function(e) {
let text = e.target.result;
// Now you have the contents of the file
let sentences = document.createElement('ul');
sentences.id = 'sentences';
sentences.innerHTML = text;
contents.appendChild(sentences);
let paragraphs = sentences.querySelectorAll('li');
sentences.innerHTML = "";
// Add event listeners to each <p> element
paragraphs.forEach(function(p) {
p.addEventListener('click', function() {
// Define what happens when a <p> is clicked
console.log('Paragraph clicked:', p.textContent);
askChat(p.textContent);
});
sentences.appendChild(p);
});
// insertDivs(contents, text);
// console.log(contents); // You can process the file contents here
};
reader.readAsText(file.files[0]); // Read the first selected file
}
});
// Create a button for selecting files.
let button = document.createElement('button'); button.id = 'buttonLoad'; button.innerText = 'Select File';
button.onclick = function() {
file.click(); // Trigger the file input when button is clicked
};
let container = document.getElementById("prompt-textarea").parentNode.parentNode.parentNode;
container.appendChild(button);
}
createSentenceLists();
function createSelectMenu() {
// HTML for the language selector
const html = `
<select id="languageSelect" class="language-select">
<option value="JA">JA</option>
<option value="EN">EN</option>
<option value="ZH">ZH</option>
</select>
`;
const menu = document.createElement('div');
menu.style.display = 'flex';
menu.style.position = 'absolute';
menu.style.left = '-160px';
// Inject HTML into the body (You may want to adjust where exactly it is added)
let container = document.getElementById("prompt-textarea").parentNode.parentNode.parentNode;
container.appendChild(menu);
menu.innerHTML = html;
// Get the select element
const languageSelect = document.getElementById('languageSelect');
// Set the stored value on page load
const savedLanguage = localStorage.getItem('selectedLanguage');
if (savedLanguage) {
languageSelect.value = savedLanguage;
}
// Add event listener to store selection
languageSelect.addEventListener('change', function() {
localStorage.setItem('selectedLanguage', languageSelect.value);
});
}
createSelectMenu();
function createCustomButton() {
let newButton = document.createElement('askButton');
newButton.innerHTML = '?';
// Set the position of the new button relative to the send button
newButton.style.display = 'flex';
newButton.style.position = 'absolute';
newButton.style.left = '-80px';
// newButton.style.right = (30) + 'px'; // Adjust this value to move the button left of the send button
// newButton.style.bottom = 100 + 'px';
// Basic styling to make it look like a traditional button
// newButton.style.backgroundColor = '#007bff'; // Button background color
newButton.style.color = '#007bff'; // Text color
newButton.style.padding = '10px 20px'; // Padding inside the button
newButton.style.border = '1px solid #007bff'; // No border
newButton.style.borderRadius = '10px'; // Rounded corners
newButton.style.cursor = 'pointer'; // Cursor changes on hover
newButton.style.fontSize = '16px'; // Font size
newButton.style.fontWeight = 'bold'; // Font weight
let container = document.getElementById("prompt-textarea").parentNode.parentNode.parentNode;
// Append the new button to the same parent as the send button
container.appendChild(newButton);
newButton.addEventListener('click', function() {
navigator.clipboard.readText()
.then(text => askChat(text))
.catch(err => {
// Handle errors (like if clipboard access is denied)
console.error('Failed to read clipboard contents: ', err);
});
});
}
createCustomButton();
})();