General Calculator

Calculator that should work on every page :p

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

  1. // ==UserScript==
  2. // @name General Calculator
  3. // @namespace https://greasyfork.org/en/users/1291009
  4. // @version 1.9.4
  5. // @description Calculator that should work on every page :p
  6. // @author BadOrBest
  7. // @license MIT
  8. // @icon https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSITQfCUO2ak5KcOYOskQl6nrLCyC7v73kkB0eIUyu5rsErnN45
  9. // @match *://*/*
  10. // @grant GM_addStyle
  11. // @grant GM_setValue
  12. // @grant GM_getValue
  13. // @grant GM_deleteValue
  14. // @run-at document-end
  15. // ==/UserScript==
  16. (function() {
  17. 'use strict';
  18.  
  19. var chatBox = document.createElement('div');
  20. chatBox.id = 'calculator-chat-box';
  21. chatBox.style.position = 'fixed';
  22. chatBox.style.bottom = '10vh'; // Adjusted for mobile viewport
  23. chatBox.style.right = '5vw'; // Adjusted for mobile viewport
  24. chatBox.style.width = 'calc(90vw - 10px)'; // Adjusted for mobile viewport
  25. chatBox.style.maxWidth = '300px';
  26. chatBox.style.overflowY = 'hidden';
  27. chatBox.style.backgroundColor = '#222';
  28. chatBox.style.borderRadius = '20px';
  29. chatBox.style.padding = '0';
  30. chatBox.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
  31. chatBox.style.zIndex = '9999';
  32. chatBox.style.display = 'flex';
  33. chatBox.style.flexDirection = 'column';
  34.  
  35. // Draggable functionality
  36. var isDragging = false;
  37. var initialX, initialY;
  38. var offsetX = 0;
  39. var offsetY = 0;
  40.  
  41. chatBox.addEventListener('mousedown', startDragging);
  42. chatBox.addEventListener('touchstart', startDragging);
  43.  
  44. document.addEventListener('keydown', handleArrowKeys);
  45.  
  46. function startDragging(event) {
  47. event.preventDefault();
  48. if (event.type === 'mousedown') {
  49. initialX = event.clientX - offsetX;
  50. initialY = event.clientY - offsetY;
  51. } else if (event.type === 'touchstart') {
  52. initialX = event.touches[0].clientX - offsetX;
  53. initialY = event.touches[0].clientY - offsetY;
  54. }
  55. isDragging = true;
  56. chatBox.classList.add('chat-dragging');
  57.  
  58. document.addEventListener('mousemove', drag);
  59. document.addEventListener('touchmove', drag);
  60.  
  61. document.addEventListener('mouseup', stopDragging);
  62. document.addEventListener('touchend', stopDragging);
  63. }
  64.  
  65. function drag(event) {
  66. event.preventDefault();
  67. if (isDragging) {
  68. var currentX, currentY;
  69. if (event.type === 'mousemove') {
  70. currentX = event.clientX - initialX;
  71. currentY = event.clientY - initialY;
  72. } else if (event.type === 'touchmove') {
  73. currentX = event.touches[0].clientX - initialX;
  74. currentY = event.touches[0].clientY - initialY;
  75. }
  76.  
  77. offsetX = currentX;
  78. offsetY = currentY;
  79.  
  80. chatBox.style.transform = `translate(${currentX}px, ${currentY}px)`;
  81. }
  82. }
  83.  
  84. function stopDragging() {
  85. isDragging = false;
  86. chatBox.classList.remove('chat-dragging');
  87.  
  88. document.removeEventListener('mousemove', drag);
  89. document.removeEventListener('touchmove', drag);
  90.  
  91. document.removeEventListener('mouseup', stopDragging);
  92. document.removeEventListener('touchend', stopDragging);
  93. }
  94.  
  95. function handleArrowKeys(event) {
  96. if (isDragging) {
  97. return;
  98. }
  99. var step = 10;
  100. switch (event.key) {
  101. case 'ArrowUp':
  102. offsetY -= step;
  103. break;
  104. case 'ArrowDown':
  105. offsetY += step;
  106. break;
  107. case 'ArrowLeft':
  108. offsetX -= step;
  109. break;
  110. case 'ArrowRight':
  111. offsetX += step;
  112. break;
  113. }
  114. chatBox.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
  115. }
  116.  
  117. // Title
  118. var chatTitle = document.createElement('div');
  119. chatTitle.style.background = '#444';
  120. chatTitle.style.color = 'white';
  121. chatTitle.style.padding = '10px';
  122. chatTitle.style.textAlign = 'center';
  123. chatTitle.style.fontWeight = 'bold';
  124. chatTitle.textContent = 'Calculator';
  125. chatBox.appendChild(chatTitle);
  126.  
  127. // Collapse Button
  128. var collapseButton = document.createElement('button');
  129. collapseButton.textContent = '▼';
  130. collapseButton.style.position = 'absolute';
  131. collapseButton.style.top = '0';
  132. collapseButton.style.right = '0';
  133. collapseButton.style.margin = '10px';
  134. collapseButton.style.width = '30px';
  135. collapseButton.style.height = '30px';
  136. collapseButton.style.fontSize = '20px';
  137. collapseButton.style.border = 'none';
  138. collapseButton.style.backgroundColor = '#444';
  139. collapseButton.style.color = 'white';
  140. collapseButton.style.cursor = 'pointer';
  141. collapseButton.style.borderRadius = '50%';
  142. collapseButton.addEventListener('click', function() {
  143. toggleChatBox();
  144. });
  145. chatBox.appendChild(collapseButton);
  146.  
  147. // Toggle chat box visibility
  148. function toggleChatBox() {
  149. if (chatBox.style.height === 'auto' || chatBox.style.height === '') {
  150. chatBox.style.height = '70px'; // Set to a fixed height
  151. collapseButton.textContent = '▲';
  152. chatInput.style.display = 'none'; // Hide the input field
  153. } else {
  154. chatBox.style.height = 'auto';
  155. collapseButton.textContent = '▼';
  156. chatInput.style.display = 'block'; // Show the input field
  157. }
  158. }
  159.  
  160. // Chat history container
  161. var chatHistory = document.createElement('div');
  162. chatHistory.id = 'chat-history';
  163. chatHistory.style.height = 'calc(50vh - 110px)';
  164. chatHistory.style.overflowY = 'auto';
  165. chatHistory.style.backgroundColor = '#333';
  166. chatBox.appendChild(chatHistory);
  167.  
  168. // Function to add message to conversation
  169. function addMessage(message, isInput) {
  170. var messageElement = document.createElement('div');
  171. messageElement.className = 'message ' + (isInput ? 'input' : 'output');
  172. messageElement.innerHTML = message;
  173. chatHistory.appendChild(messageElement);
  174.  
  175. if (!isInput) {
  176. var line = document.createElement('hr');
  177. line.style.borderTop = '1px solid white';
  178. line.style.margin = '5px 0';
  179. chatHistory.appendChild(line);
  180. }
  181.  
  182. chatHistory.scrollTop = chatHistory.scrollHeight;
  183. }
  184.  
  185. // Function to evaluate and display the result
  186. function evaluateExpression(expression) {
  187. try {
  188. // Replace 'x' with '*' for mathematical operations
  189. expression = expression.replace(/(x)/g, '*');
  190. // Handling algebraic expressions
  191. var result;
  192. if (/\b[A-Za-z]+\b/.test(expression)) {
  193. // If expression contains letters
  194. var match = expression.match(/\b[A-Za-z]+\b/);
  195. var letter = match[0];
  196. var equation = expression.replace(/\b[A-Za-z]+\b/g, '0'); // Replace letters with '0' for evaluation
  197. result = solveEquation(equation, letter);
  198. } else {
  199. // If expression is purely mathematical
  200. result = eval(expression);
  201. }
  202. addMessage('<span class="bot-label">(Computer):</span> ' + result, false);
  203. } catch (error) {
  204. addMessage('<span class="bot-label">(Computer):</span> Error: ' + error.message, false);
  205. }
  206. }
  207.  
  208. // Function to solve algebraic equation
  209. function solveEquation(equation, letter) {
  210. // For simplicity, let's assume linear equations of the form 'ax = b'
  211. var sides = equation.split('=');
  212. var a = eval(sides[0]);
  213. var b = eval(sides[1]);
  214. var result = b / a;
  215. return letter + ' = ' + result;
  216. }
  217.  
  218. // Function to send message
  219. function sendMessage() {
  220. var expression = chatInput.value.trim();
  221. if (expression !== '') {
  222. addMessage('<span class="user-label">(User):</span> ' + expression, true);
  223. evaluateExpression(expression);
  224. chatInput.value = '';
  225. }
  226. }
  227.  
  228. // Input field
  229. var chatInput = document.createElement('input');
  230. chatInput.type = 'text';
  231. chatInput.placeholder = 'Type here...';
  232. chatInput.style.width = 'calc(100% - 20px)';
  233. chatInput.style.padding = '10px';
  234. chatInput.style.margin = '10px auto'; // Centered horizontally
  235. chatInput.style.borderRadius = '10px';
  236. chatInput.style.border = 'none';
  237. chatInput.style.backgroundColor = '#444';
  238. chatInput.style.color = 'white';
  239. chatInput.style.zIndex = '10000'; // Ensure input field is above other elements
  240. chatBox.appendChild(chatInput);
  241.  
  242. // Listen for Enter key press to send message
  243. chatInput.addEventListener('keydown', function(event) {
  244. if (event.key === 'Enter') {
  245. event.preventDefault();
  246. sendMessage();
  247. }
  248. });
  249.  
  250. // CSS style for user and bot messages
  251. var style = document.createElement('style');
  252. style.innerHTML = `
  253. .message {
  254. clear: both;
  255. padding: 5px 10px;
  256. color: white;
  257. }
  258. .input {
  259. text-align: left;
  260. }
  261. .bot-label {
  262. float: left;
  263. margin-left: 5px;
  264. background-color: blue;
  265. color: white;
  266. border-radius: 10px;
  267. padding: 3px 6px;
  268. }
  269. .user-label {
  270. float: left;
  271. margin-left: 5px;
  272. background-color: green;
  273. color: white;
  274. border-radius: 10px;
  275. padding: 3px 6px;
  276. }
  277. hr {
  278. border-top: 1px solid white;
  279. margin: 5px 0;
  280. }
  281. .chat-dragging * {
  282. /* Removed user-select: none; to enable touch interactions */
  283. }
  284. `;
  285. document.head.appendChild(style);
  286.  
  287. // Append chatBox to body
  288. document.body.appendChild(chatBox);
  289. })();
  290.  
  291.  
  292. // Mathematical functions
  293. Math.sinh = function(x) { return (Math.exp(x) - Math.exp(-x)) / 2; };
  294. Math.cosh = function(x) { return (Math.exp(x) + Math.exp(-x)) / 2; };
  295. Math.tanh = function(x) { return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x)); };
  296. Math.asinh = function(x) { return Math.log(x + Math.sqrt(x * x + 1)); };
  297. Math.acosh = function(x) { return Math.log(x + Math.sqrt(x * x - 1)); };
  298. Math.atanh = function(x) { return Math.log((1 + x) / (1 - x)) / 2; };
  299.  
  300. // Mathematical constants
  301. var E = Math.E; // Euler's number
  302. var PI = Math.PI; // Pi
  303. var SQRT2 = Math.SQRT2; // Square root of 2
  304. var SQRT1_2 = Math.SQRT1_2; // Square root of 1/2
  305.  
  306. // Additional mathematical operations
  307. Math.factorial = function(n) {
  308. if (n === 0 || n === 1)
  309. return 1;
  310. for (var i = n - 1; i >= 1; i--) {
  311. n *= i;
  312. }
  313. return n;
  314. };
  315.  
  316. Math.permutation = function(n, r) {
  317. return Math.factorial(n) / Math.factorial(n - r);
  318. };
  319.  
  320. Math.combination = function(n, r) {
  321. return Math.factorial(n) / (Math.factorial(r) * Math.factorial(n - r));
  322. };
  323.  
  324. Math.roundTo = function(value, decimalPlaces) {
  325. var multiplier = Math.pow(10, decimalPlaces);
  326. return Math.round(value * multiplier) / multiplier;
  327. };
  328.  
  329. // Trigonometric functions
  330. Math.degToRad = function(degrees) {
  331. return degrees * (Math.PI / 180);
  332. };
  333.  
  334. Math.radToDeg = function(radians) {
  335. return radians * (180 / Math.PI);
  336. };
  337.  
  338. // Logarithmic functions
  339. Math.log10 = function(x) {
  340. return Math.log(x) / Math.log(10);
  341. };
  342.  
  343. Math.log2 = function(x) {
  344. return Math.log(x) / Math.log(2);
  345. };
  346.  
  347. // Exponential functions
  348. Math.exp10 = function(x) {
  349. return Math.pow(10, x);
  350. };
  351.  
  352. Math.exp2 = function(x) {
  353. return Math.pow(2, x);
  354. };
  355.  
  356. // Additional mathematical functions
  357. Math.abs = function(x) { return Math.abs(x); };
  358. Math.ceil = function(x) { return Math.ceil(x); };
  359. Math.floor = function(x) { return Math.floor(x); };
  360. Math.max = function(...args) { return Math.max(...args); };
  361. Math.min = function(...args) { return Math.min(...args); };
  362. Math.pow = function(x, y) { return Math.pow(x, y); };
  363. Math.sqrt = function(x) { return Math.sqrt(x); };
  364. Math.sign = function(x) { return Math.sign(x); };
  365. Math.randomInt = function(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; };
  366. Math.clamp = function(x, min, max) { return Math.max(min, Math.min(max, x)); };
  367. Math.hypot = function(...args) { return Math.hypot(...args); };
  368.  
  369. // Constants
  370. var LN2 = Math.LN2; // Natural logarithm of 2
  371. var LN10 = Math.LN10; // Natural logarithm of 10
  372. var LOG2E = Math.LOG2E; // Base 2 logarithm of E
  373. var LOG10E = Math.LOG10E; // Base 10 logarithm of E
  374. var SQRT3 = Math.SQRT3; // Square root of 3
  375.  
  376. // Exponential constants
  377. var EXP = Math.exp(1); // Euler's number
  378.  
  379. // Trigonometric constants
  380. var DEG_PER_RAD = 180 / Math.PI; // Degrees per radian
  381. var RAD_PER_DEG = Math.PI / 180; // Radians per degree
  382. var TWO_PI = 2 * Math.PI; // 2 * Pi
  383.  
  384. // Logarithmic constants
  385. var LN_2 = Math.LN2; // Natural logarithm of 2
  386. var LN_10 = Math.LN10; // Natural logarithm of 10
  387. var LOG2_E = Math.LOG2E; // Base 2 logarithm of E
  388. var LOG10_E = Math.LOG10E; // Base 10 logarithm of E
  389.  
  390. // Exponential constants
  391. var SQRT_2 = Math.SQRT2; // Square root of 2
  392. var SQRT_1_2 = Math.SQRT1_2; // Square root of 1/2
  393.  
  394. // Additional mathematical operations
  395. Math.lcm = function(a, b) { return (!a || !b) ? 0 : Math.abs((a * b) / Math.gcd(a, b)); };
  396. Math.gcd = function(a, b) { return (!b) ? a : Math.gcd(b, a % b); };
  397. Math.factorial = function(n) { return (n !== 1 && n !== 0) ? n * Math.factorial(n - 1) : 1; };
  398. Math.toDegrees = function(radians) { return radians * DEG_PER_RAD; };
  399. Math.toRadians = function(degrees) { return degrees * RAD_PER_DEG; };
  400. Math.isPrime = function(n) {
  401. if (n <= 1) return false;
  402. if (n <= 3) return true;
  403. if (n % 2 === 0 || n % 3 === 0) return false;
  404. let i = 5;
  405. while (i * i <= n) {
  406. if (n % i === 0 || n % (i + 2) === 0) return false;
  407. i += 6;
  408. }
  409. return true;
  410. };