General Calculator

Calculator that should work on every page :p

当前为 2024-06-10 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         General Calculator
// @namespace    https://greasyfork.org/en/users/1291009
// @version      2.0
// @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
// @run-at       document-end
// ==/UserScript==
(function() {
    'use strict';

    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 add message to conversation
    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);
        }

        chatHistory.scrollTop = chatHistory.scrollHeight;
    }

    // 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">(Computer):</span> ' + result, false);
        } catch (error) {
            addMessage('<span class="bot-label">(Computer):</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);
})();


// 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;
};