您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a draggable floating button to copy the current page's title and URL, with enhanced UI and error handling
当前为
// ==UserScript== // @name Copy URL and Title (Enhanced UI and Error Handling) // @namespace http://tampermonkey.net/ // @version 1.4 // @description Adds a draggable floating button to copy the current page's title and URL, with enhanced UI and error handling // @match *://*/* // @grant GM_setClipboard // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // @license GPL-3.0 // ==/UserScript== (function() { 'use strict'; // Helper function to generate UUID function generateUUID() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } // Initialize settings let settings = GM_getValue('settings', { account: generateUUID().slice(0, 10), accessToken: generateUUID(), serverUrl: 'http://localhost:5000/api/save' }); // Create floating button const button = document.createElement('div'); button.innerHTML = '📋'; button.style.cssText = ` position: fixed; bottom: 20px; right: 20px; width: 50px; height: 50px; background-color: #4CAF50; color: white; border-radius: 50%; text-align: center; line-height: 50px; font-size: 24px; cursor: move; z-index: 9999; box-shadow: 0 2px 5px rgba(0,0,0,0.3); transition: background-color 0.3s; `; // Create popup const popup = document.createElement('div'); popup.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: white; padding: 20px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.2); z-index: 10000; display: none; `; // Add button and popup to the page document.body.appendChild(button); document.body.appendChild(popup); // Dragging functionality (unchanged) let isDragging = false; let startX, startY, startLeft, startTop; button.addEventListener('mousedown', function(e) { isDragging = true; startX = e.clientX; startY = e.clientY; startLeft = parseInt(window.getComputedStyle(button).left); startTop = parseInt(window.getComputedStyle(button).top); e.preventDefault(); }); document.addEventListener('mousemove', function(e) { if (!isDragging) return; let newLeft = startLeft + e.clientX - startX; let newTop = startTop + e.clientY - startY; newLeft = Math.max(0, Math.min(newLeft, window.innerWidth - button.offsetWidth)); newTop = Math.max(0, Math.min(newTop, window.innerHeight - button.offsetHeight)); button.style.left = newLeft + 'px'; button.style.top = newTop + 'px'; button.style.bottom = 'auto'; button.style.right = 'auto'; }); document.addEventListener('mouseup', function() { isDragging = false; }); // Button click event button.addEventListener('click', function(e) { if (isDragging) return; const pageTitle = document.title; const pageUrl = window.location.href; const copyText = `${pageTitle}\n${pageUrl}`; GM_setClipboard(copyText, 'text'); // Send data to server GM_xmlhttpRequest({ method: "POST", url: settings.serverUrl, data: JSON.stringify({ account: settings.account, accessToken: settings.accessToken, title: pageTitle, url: pageUrl }), headers: { "Content-Type": "application/json" }, onload: function(response) { if (response.status === 200) { button.innerHTML = '✅'; button.style.backgroundColor = '#45a049'; console.log("Data sent to server successfully:", response.responseText); } else { button.innerHTML = '❌'; button.style.backgroundColor = '#f44336'; console.error("Failed to send data to server:", response.statusText); } }, onerror: function(response) { button.innerHTML = '❌'; button.style.backgroundColor = '#f44336'; console.error("Failed to send data to server:", response.statusText); } }); popup.innerHTML = ` <h3>Copied to clipboard and sending to server:</h3> <p><strong>Title:</strong> ${pageTitle}</p> <p><strong>URL:</strong> ${pageUrl}</p> <button id="closePopup" style="margin-top: 10px;">Close</button> `; popup.style.display = 'block'; document.getElementById('closePopup').addEventListener('click', function() { popup.style.display = 'none'; }); }); // Settings popup function showSettings() { const settingsPopup = document.createElement('div'); settingsPopup.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: white; padding: 30px; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.2); z-index: 10001; font-family: Arial, sans-serif; width: 300px; `; settingsPopup.innerHTML = ` <h2 style="margin-top: 0; color: #333;">Settings</h2> <div style="margin-bottom: 15px;"> <label for="account" style="display: block; margin-bottom: 5px; color: #666;">Account:</label> <input type="text" id="account" value="${settings.account}" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;"> </div> <div style="margin-bottom: 15px;"> <label for="accessToken" style="display: block; margin-bottom: 5px; color: #666;">Access Token:</label> <input type="text" id="accessToken" value="${settings.accessToken}" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;"> </div> <div style="margin-bottom: 15px;"> <label for="serverUrl" style="display: block; margin-bottom: 5px; color: #666;">Server URL:</label> <textarea id="serverUrl" style="width: 100%; height: 60px; padding: 8px; border: 1px solid #ddd; border-radius: 4px; resize: vertical;">${settings.serverUrl}</textarea> </div> <div style="text-align: right;"> <button id="saveSettings" style="background-color: #4CAF50; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer; margin-right: 10px;">Save</button> <button id="closeSettings" style="background-color: #f44336; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer;">Close</button> </div> `; document.body.appendChild(settingsPopup); document.getElementById('saveSettings').addEventListener('click', function() { settings.account = document.getElementById('account').value; settings.accessToken = document.getElementById('accessToken').value; settings.serverUrl = document.getElementById('serverUrl').value; GM_setValue('settings', settings); settingsPopup.remove(); }); document.getElementById('closeSettings').addEventListener('click', function() { settingsPopup.remove(); }); } // Right-click menu for settings button.addEventListener('contextmenu', function(e) { e.preventDefault(); showSettings(); }); // Register menu command for Tampermonkey GM_registerMenuCommand("Settings", showSettings); // Reset button state when the page is about to unload window.addEventListener('beforeunload', function() { button.innerHTML = '📋'; button.style.backgroundColor = '#4CAF50'; }); })();