您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Calculator that should work on every page :p
当前为
// ==UserScript== // @name General Calculator // @namespace https://greasyfork.org/en/users/1291009 // @version 2.2 // @description Calculator that should work on every page :p // @author BadOrBest // @license MIT // @icon https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSITQfCUO2ak5KcOYOskQl6nrLCyC7v73kkB0eIUyu5rsErnN45 // @match *://*/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM.registerMenuCommand // @run-at document-end // ==/UserScript== (function() { 'use strict'; var MAX_MESSAGES = 400; // Maximum number of messages to store var chatBox = document.createElement('div'); chatBox.id = 'calculator-chat-box'; chatBox.style.position = 'fixed'; chatBox.style.bottom = '10vh'; // Adjusted for mobile viewport chatBox.style.right = '5vw'; // Adjusted for mobile viewport chatBox.style.width = 'calc(90vw - 10px)'; // Adjusted for mobile viewport chatBox.style.maxWidth = '300px'; chatBox.style.overflowY = 'hidden'; chatBox.style.backgroundColor = '#222'; chatBox.style.borderRadius = '20px'; chatBox.style.padding = '0'; chatBox.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)'; chatBox.style.zIndex = '9999'; chatBox.style.display = 'flex'; chatBox.style.flexDirection = 'column'; // Draggable functionality var isDragging = false; var initialX, initialY; var offsetX = 0; var offsetY = 0; var selectedForArrowKeys = false; // Added variable to track if chatBox is selected for arrow key dragging chatBox.addEventListener('mousedown', startDragging); chatBox.addEventListener('touchstart', startDragging); chatBox.addEventListener('click', selectForArrowKeys); // Listen for click to select chatBox for arrow key dragging // Listen for click events on the document to unselect the chatbox document.addEventListener('click', function(event) { if (!chatBox.contains(event.target)) { selectedForArrowKeys = false; // Clicked outside of the chatbox, unselect it } }); document.addEventListener('keydown', handleArrowKeys); function startDragging(event) { if (event.target === chatInput) { return; // Don't start dragging if clicking on the input field } event.preventDefault(); if (event.type === 'mousedown') { initialX = event.clientX - offsetX; initialY = event.clientY - offsetY; } else if (event.type === 'touchstart') { initialX = event.touches[0].clientX - offsetX; initialY = event.touches[0].clientY - offsetY; } isDragging = true; chatBox.classList.add('chat-dragging'); document.addEventListener('mousemove', drag); document.addEventListener('touchmove', drag); document.addEventListener('mouseup', stopDragging); document.addEventListener('touchend', stopDragging); } function drag(event) { event.preventDefault(); if (isDragging) { var currentX, currentY; if (event.type === 'mousemove') { currentX = event.clientX - initialX; currentY = event.clientY - initialY; } else if (event.type === 'touchmove') { currentX = event.touches[0].clientX - initialX; currentY = event.touches[0].clientY - initialY; } offsetX = currentX; offsetY = currentY; chatBox.style.transform = `translate(${currentX}px, ${currentY}px)`; } } function stopDragging() { isDragging = false; chatBox.classList.remove('chat-dragging'); document.removeEventListener('mousemove', drag); document.removeEventListener('touchmove', drag); document.removeEventListener('mouseup', stopDragging); document.removeEventListener('touchend', stopDragging); } function handleArrowKeys(event) { if (!selectedForArrowKeys) { return; // If chatBox is not selected for arrow key dragging, exit function } var step = 10; switch (event.key) { case 'ArrowUp': offsetY -= step; break; case 'ArrowDown': offsetY += step; break; case 'ArrowLeft': offsetX -= step; break; case 'ArrowRight': offsetX += step; break; } chatBox.style.transform = `translate(${offsetX}px, ${offsetY}px)`; } function selectForArrowKeys(event) { selectedForArrowKeys = true; // Set chatBox as selected for arrow key dragging } // Title var chatTitle = document.createElement('div'); chatTitle.style.background = '#444'; chatTitle.style.color = 'white'; chatTitle.style.padding = '10px'; chatTitle.style.textAlign = 'center'; chatTitle.style.fontWeight = 'bold'; chatTitle.textContent = 'Calculator'; chatBox.appendChild(chatTitle); // Collapse Button var collapseButton = document.createElement('button'); collapseButton.textContent = '▼'; collapseButton.style.position = 'absolute'; collapseButton.style.top = '0'; collapseButton.style.right = '0'; collapseButton.style.margin = '10px'; collapseButton.style.width = '30px'; collapseButton.style.height = '30px'; collapseButton.style.fontSize = '20px'; collapseButton.style.border = 'none'; collapseButton.style.backgroundColor = '#444'; collapseButton.style.color = 'white'; collapseButton.style.cursor = 'pointer'; collapseButton.style.borderRadius = '50%'; // Add click event listener collapseButton.addEventListener('click', function(event) { toggleChatBox(event); }); // Add touch event listener collapseButton.addEventListener('touchstart', function(event) { toggleChatBox(event); }); chatBox.appendChild(collapseButton); // Toggle chat box visibility function toggleChatBox(event) { // Stop propagation of the click event to prevent it from triggering dragging event.stopPropagation(); if (chatBox.style.height === 'auto' || chatBox.style.height === '') { chatBox.style.height = '70px'; // Set to a fixed height collapseButton.textContent = '▲'; chatInput.style.display = 'none'; // Hide the input field } else { chatBox.style.height = 'auto'; collapseButton.textContent = '▼'; chatInput.style.display = 'block'; // Show the input field } } // Chat history container var chatHistory = document.createElement('div'); chatHistory.id = 'chat-history'; chatHistory.style.height = 'calc(50vh - 110px)'; chatHistory.style.overflowY = 'auto'; chatHistory.style.backgroundColor = '#333'; chatBox.appendChild(chatHistory); // Function to load messages from localStorage function loadMessagesFromStorage() { var messages = []; try { messages = JSON.parse(localStorage.getItem('chatHistory')) || []; } catch (error) { console.error('Error loading chat history from localStorage:', error); // Clear localStorage if there's an error (e.g., quota exceeded) clearLocalStorage(); } return messages; } // Function to clear localStorage function clearLocalStorage() { try { localStorage.removeItem('chatHistory'); } catch (error) { console.error('Error clearing localStorage:', error); } } // Function to add message to conversation and save to localStorage function addMessage(message, isInput) { var messageElement = document.createElement('div'); messageElement.className = 'message ' + (isInput ? 'input' : 'output'); messageElement.innerHTML = message; chatHistory.appendChild(messageElement); if (!isInput) { var line = document.createElement('hr'); line.style.borderTop = '1px solid white'; line.style.margin = '5px 0'; chatHistory.appendChild(line); } // Function to scroll to the bottom of the chat history function scrollToBottom() { chatHistory.scrollTop = chatHistory.scrollHeight; } // Function to check and scroll to bottom if necessary function checkAndScrollToBottom() { // Check if user is already at the bottom or if there's a new message if (chatHistory.scrollTop + chatHistory.clientHeight === chatHistory.scrollHeight) { scrollToBottom(); } } // Initial scroll to bottom when the page loads or chat initializes scrollToBottom(); // Save message to localStorage var messages = loadMessagesFromStorage(); messages.push({ message: message, isInput: isInput }); // Limit messages to MAX_MESSAGES if (messages.length > MAX_MESSAGES) { messages = messages.slice(-MAX_MESSAGES); } try { localStorage.setItem('chatHistory', JSON.stringify(messages)); } catch (error) { console.error('Error saving chat history to localStorage:', error); // Clear localStorage if there's an error (e.g., quota exceeded) clearLocalStorage(); } } // Function to evaluate and display the result function evaluateExpression(expression) { try { // Replace 'x' with '*' for mathematical operations expression = expression.replace(/(x)/g, '*'); // Handling algebraic expressions var result; if (/\b[A-Za-z]+\b/.test(expression)) { // If expression contains letters var match = expression.match(/\b[A-Za-z]+\b/); var letter = match[0]; var equation = expression.replace(/\b[A-Za-z]+\b/g, '0'); // Replace letters with '0' for evaluation result = solveEquation(equation, letter); } else { // If expression is purely mathematical result = eval(expression); } addMessage('<span class="bot-label">(Calc):</span> ' + result, false); } catch (error) { addMessage('<span class="bot-label">(Calc):</span> Error: ' + error.message, false); } } // Function to solve algebraic equation function solveEquation(equation, letter) { // For simplicity, let's assume linear equations of the form 'ax = b' var sides = equation.split('='); var a = eval(sides[0]); var b = eval(sides[1]); var result = b / a; return letter + ' = ' + result; } // Function to send message function sendMessage() { var expression = chatInput.value.trim(); if (expression !== '') { addMessage('<span class="user-label">(User):</span> ' + expression, true); evaluateExpression(expression); chatInput.value = ''; } } // Input field var chatInput = document.createElement('input'); chatInput.type = 'text'; chatInput.placeholder = 'Type here...'; chatInput.style.width = 'calc(100% - 20px)'; chatInput.style.padding = '10px'; chatInput.style.margin = '10px auto'; // Centered horizontally chatInput.style.borderRadius = '10px'; chatInput.style.border = 'none'; chatInput.style.backgroundColor = '#444'; chatInput.style.color = 'white'; chatInput.style.zIndex = '10000'; // Ensure input field is above other elements chatBox.appendChild(chatInput); // Listen for Enter key press to send message chatInput.addEventListener('keydown', function(event) { if (event.key === 'Enter') { event.preventDefault(); sendMessage(); } }); // CSS style for user and bot messages var style = document.createElement('style'); style.innerHTML = ` .message { clear: both; padding: 5px 10px; color: white; } .input { text-align: left; } .bot-label { float: left; margin-left: 5px; background-color: blue; color: white; border-radius: 10px; padding: 3px 6px; } .user-label { float: left; margin-left: 5px; background-color: green; color: white; border-radius: 10px; padding: 3px 6px; } hr { border-top: 1px solid white; margin: 5px 0; } .chat-dragging * { /* Removed user-select: none; to enable touch interactions */ } `; document.head.appendChild(style); // Append chatBox to body document.body.appendChild(chatBox); // Load messages from localStorage on page load window.addEventListener('load', function() { var messages = loadMessagesFromStorage(); messages.forEach(function(msg) { addMessage(msg.message, msg.isInput); }); }); })(); // Mathematical functions Math.sinh = function(x) { return (Math.exp(x) - Math.exp(-x)) / 2; }; Math.cosh = function(x) { return (Math.exp(x) + Math.exp(-x)) / 2; }; Math.tanh = function(x) { return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x)); }; Math.asinh = function(x) { return Math.log(x + Math.sqrt(x * x + 1)); }; Math.acosh = function(x) { return Math.log(x + Math.sqrt(x * x - 1)); }; Math.atanh = function(x) { return Math.log((1 + x) / (1 - x)) / 2; }; // Mathematical constants var E = Math.E; // Euler's number var PI = Math.PI; // Pi var SQRT2 = Math.SQRT2; // Square root of 2 var SQRT1_2 = Math.SQRT1_2; // Square root of 1/2 // Additional mathematical operations Math.factorial = function(n) { if (n === 0 || n === 1) return 1; for (var i = n - 1; i >= 1; i--) { n *= i; } return n; }; Math.permutation = function(n, r) { return Math.factorial(n) / Math.factorial(n - r); }; Math.combination = function(n, r) { return Math.factorial(n) / (Math.factorial(r) * Math.factorial(n - r)); }; Math.roundTo = function(value, decimalPlaces) { var multiplier = Math.pow(10, decimalPlaces); return Math.round(value * multiplier) / multiplier; }; // Trigonometric functions Math.degToRad = function(degrees) { return degrees * (Math.PI / 180); }; Math.radToDeg = function(radians) { return radians * (180 / Math.PI); }; // Logarithmic functions Math.log10 = function(x) { return Math.log(x) / Math.log(10); }; Math.log2 = function(x) { return Math.log(x) / Math.log(2); }; // Exponential functions Math.exp10 = function(x) { return Math.pow(10, x); }; Math.exp2 = function(x) { return Math.pow(2, x); }; // Additional mathematical functions Math.abs = function(x) { return Math.abs(x); }; Math.ceil = function(x) { return Math.ceil(x); }; Math.floor = function(x) { return Math.floor(x); }; Math.max = function(...args) { return Math.max(...args); }; Math.min = function(...args) { return Math.min(...args); }; Math.pow = function(x, y) { return Math.pow(x, y); }; Math.sqrt = function(x) { return Math.sqrt(x); }; Math.sign = function(x) { return Math.sign(x); }; Math.randomInt = function(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }; Math.clamp = function(x, min, max) { return Math.max(min, Math.min(max, x)); }; Math.hypot = function(...args) { return Math.hypot(...args); }; // Constants var LN2 = Math.LN2; // Natural logarithm of 2 var LN10 = Math.LN10; // Natural logarithm of 10 var LOG2E = Math.LOG2E; // Base 2 logarithm of E var LOG10E = Math.LOG10E; // Base 10 logarithm of E var SQRT3 = Math.SQRT3; // Square root of 3 // Exponential constants var EXP = Math.exp(1); // Euler's number // Trigonometric constants var DEG_PER_RAD = 180 / Math.PI; // Degrees per radian var RAD_PER_DEG = Math.PI / 180; // Radians per degree var TWO_PI = 2 * Math.PI; // 2 * Pi // Logarithmic constants var LN_2 = Math.LN2; // Natural logarithm of 2 var LN_10 = Math.LN10; // Natural logarithm of 10 var LOG2_E = Math.LOG2E; // Base 2 logarithm of E var LOG10_E = Math.LOG10E; // Base 10 logarithm of E // Exponential constants var SQRT_2 = Math.SQRT2; // Square root of 2 var SQRT_1_2 = Math.SQRT1_2; // Square root of 1/2 // Additional mathematical operations Math.lcm = function(a, b) { return (!a || !b) ? 0 : Math.abs((a * b) / Math.gcd(a, b)); }; Math.gcd = function(a, b) { return (!b) ? a : Math.gcd(b, a % b); }; Math.factorial = function(n) { return (n !== 1 && n !== 0) ? n * Math.factorial(n - 1) : 1; }; Math.toDegrees = function(radians) { return radians * DEG_PER_RAD; }; Math.toRadians = function(degrees) { return degrees * RAD_PER_DEG; }; Math.isPrime = function(n) { if (n <= 1) return false; if (n <= 3) return true; if (n % 2 === 0 || n % 3 === 0) return false; let i = 5; while (i * i <= n) { if (n % i === 0 || n % (i + 2) === 0) return false; i += 6; } return true; };