Elethor Chameleon

Change colors on Elethor.com

目前为 2025-04-01 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Elethor Chameleon
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.3
  5. // @author Eugene
  6. // @description Change colors on Elethor.com
  7. // @match *://elethor.com/*
  8. // @grant GM_addStyle
  9. // @license GPL-3.0-or-later
  10. // ==/UserScript==
  11. /*
  12. * This program is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation, either version 3 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  24. */
  25. (function() {
  26. 'use strict';
  27.  
  28. // Default colors
  29. const defaultBackgroundColor = '#202c3c';
  30. const defaultActionBarColor = '#40444c';
  31. const defaultTopBarColor = '#505c6c';
  32. const defaultTextColor = '#ffffff';
  33.  
  34. // Function to set colors from localStorage or use defaults
  35. function setColors() {
  36. const appElement = document.querySelector('#app[data-v-app]');
  37. if (appElement) {
  38. const backgroundColor = localStorage.getItem('backgroundColor') || defaultBackgroundColor;
  39. appElement.style.backgroundColor = backgroundColor;
  40. backgroundColorInput.value = backgroundColor;
  41. }
  42.  
  43. const actionBarElement = document.querySelector('#currentAction.shadow.shadow-slate-800');
  44. if (actionBarElement) {
  45. const actionBarColor = localStorage.getItem('actionBarColor') || defaultActionBarColor;
  46. actionBarElement.style.backgroundColor = actionBarColor;
  47. actionBarColorInput.value = actionBarColor;
  48. }
  49.  
  50. const topBarElement = document.querySelector('nav.navbar.is-fixed-top.is-primary.shadow-sm.shadow-slate-800\\/50');
  51. if (topBarElement) {
  52. const topBarColor = localStorage.getItem('topBarColor') || defaultTopBarColor;
  53. topBarElement.style.backgroundColor = topBarColor;
  54. topBarColorInput.value = topBarColor;
  55. }
  56.  
  57. const textColor = localStorage.getItem('textColor') || defaultTextColor;
  58. document.body.style.color = textColor;
  59. textColorInput.value = textColor;
  60. applyTextColorToAll(textColor);
  61. }
  62.  
  63. // Function to apply text color to all relevant elements
  64. function applyTextColorToAll(color) {
  65. const elementsToColor = [
  66. 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'span', 'div', 'a'
  67. ];
  68. elementsToColor.forEach(selector => {
  69. const elements = document.querySelectorAll(selector);
  70. elements.forEach(el => el.style.color = color);
  71. });
  72. }
  73.  
  74. // Function to wait for elements to load
  75. function waitForElements() {
  76. const interval = setInterval(() => {
  77. const appElement = document.querySelector('#app[data-v-app]');
  78. const actionBarElement = document.querySelector('#currentAction.shadow.shadow-slate-800');
  79. const topBarElement = document.querySelector('nav.navbar.is-fixed-top.is-primary.shadow-sm.shadow-slate-800\\/50');
  80.  
  81. if (appElement && actionBarElement && topBarElement) {
  82. clearInterval(interval);
  83. setColors();
  84. addOpenButton();
  85. positionUI();
  86. // Start reapplying colors every 10 seconds
  87. }
  88. }, 1500);
  89. }
  90.  
  91. // Function to add the Open button next to the specified link
  92. function addOpenButton() {
  93. const navbarItem = document.querySelector('a[href="/corporation"].navbar-item.is-skewed');
  94. if (navbarItem) {
  95. const openButton = document.createElement('button');
  96. openButton.innerHTML = '🎨'; // Color palette symbol
  97. openButton.style.marginLeft = '10px';
  98. const topBarElement = document.querySelector('nav.navbar.is-fixed-top.is-primary.shadow-sm.shadow-slate-800\\/50');
  99. const topBarColor = topBarElement ? topBarElement.style.backgroundColor : '#2596be'; // Fallback color
  100. openButton.style.backgroundColor = topBarColor; // Match button color to top bar color
  101. openButton.style.color = '#fff';
  102. openButton.style.border = 'none';
  103. openButton.style.padding = '5px';
  104. openButton.style.borderRadius = '3px';
  105. openButton.style.cursor = 'pointer';
  106.  
  107. // Add click event to open the color changer UI
  108. openButton.addEventListener('click', () => {
  109. uiContainer.style.display = uiContainer.style.display === 'none' ? 'flex' : 'none';
  110. positionUI(); // Ensure UI is positioned correctly
  111. });
  112.  
  113. navbarItem.parentNode.insertBefore(openButton, navbarItem.nextSibling);
  114. }
  115. }
  116.  
  117. // Function to position the UI
  118. function positionUI() {
  119. const topBarElement = document.querySelector('nav.navbar.is-fixed-top.is-primary.shadow-sm.shadow-slate-800\\/50');
  120. if (topBarElement) {
  121. const { height } = topBarElement.getBoundingClientRect();
  122. uiContainer.style.top = `${height}px`; // Set UI below the navbar
  123. }
  124. }
  125.  
  126. // Create a container for the UI
  127. const uiContainer = document.createElement('div');
  128. uiContainer.id = 'colorChangerUI';
  129. uiContainer.style.position = 'fixed';
  130. uiContainer.style.padding = '10px';
  131. uiContainer.style.backgroundColor = '#505c6c';
  132. uiContainer.style.border = '1px solid #ccc';
  133. uiContainer.style.zIndex = '10000';
  134. uiContainer.style.display = 'none'; // Initially hide the UI
  135. uiContainer.style.flexDirection = 'row'; // Set horizontal layout
  136. uiContainer.style.alignItems = 'center'; // Center items vertically
  137. uiContainer.style.whiteSpace = 'nowrap'; // Prevent wrapping
  138. uiContainer.style.color = '#ffffff'; // Match text color to Top Bar Icons
  139. uiContainer.style.fontSize = '12px'; // Decrease font size
  140.  
  141. // Background Color Input for #app[data-v-app]
  142. const backgroundColorLabel = document.createElement('label');
  143. backgroundColorLabel.textContent = 'Background Color: ';
  144. uiContainer.appendChild(backgroundColorLabel);
  145.  
  146. const backgroundColorInput = document.createElement('input');
  147. backgroundColorInput.type = 'color';
  148. uiContainer.appendChild(backgroundColorInput);
  149.  
  150. // Color Input for Action Bar #currentAction
  151. const actionBarColorLabel = document.createElement('label');
  152. actionBarColorLabel.textContent = 'Action Bar Color: ';
  153. actionBarColorLabel.style.marginLeft = '10px';
  154. uiContainer.appendChild(actionBarColorLabel);
  155.  
  156. const actionBarColorInput = document.createElement('input');
  157. actionBarColorInput.type = 'color';
  158. uiContainer.appendChild(actionBarColorInput);
  159.  
  160. // Color Input for Top Bar nav.navbar
  161. const topBarColorLabel = document.createElement('label');
  162. topBarColorLabel.textContent = 'Top Bar Color: ';
  163. topBarColorLabel.style.marginLeft = '10px';
  164. uiContainer.appendChild(topBarColorLabel);
  165.  
  166. const topBarColorInput = document.createElement('input');
  167. topBarColorInput.type = 'color';
  168. uiContainer.appendChild(topBarColorInput);
  169.  
  170. // Color Input for Text Color
  171. const textColorLabel = document.createElement('label');
  172. textColorLabel.textContent = 'Text Color: ';
  173. textColorLabel.style.marginLeft = '10px';
  174. uiContainer.appendChild(textColorLabel);
  175.  
  176. const textColorInput = document.createElement('input');
  177. textColorInput.type = 'color';
  178. uiContainer.appendChild(textColorInput);
  179.  
  180. // Save Button
  181. const saveButton = document.createElement('button');
  182. saveButton.textContent = 'Save';
  183. saveButton.style.marginLeft = '10px';
  184. uiContainer.appendChild(saveButton);
  185.  
  186. // Reset Button
  187. const resetButton = document.createElement('button');
  188. resetButton.textContent = 'Reset';
  189. resetButton.style.marginLeft = '5px';
  190. uiContainer.appendChild(resetButton);
  191. // Create Export Button
  192. const exportButton = document.createElement('button');
  193. exportButton.textContent = 'Export';
  194. exportButton.style.marginLeft = '5px';
  195. exportButton.style.backgroundColor = '#2596be'; // Blue color
  196. uiContainer.appendChild(exportButton);
  197.  
  198. // Create Import Button
  199. const importButton = document.createElement('button');
  200. importButton.textContent = 'Import';
  201. importButton.style.marginLeft = '5px';
  202. importButton.style.backgroundColor = '#2596be'; // Blue color
  203. uiContainer.appendChild(importButton);
  204.  
  205. // Export color scheme to clipboard
  206. exportButton.addEventListener('click', () => {
  207. const colorScheme = {
  208. backgroundColor: backgroundColorInput.value,
  209. actionBarColor: actionBarColorInput.value,
  210. topBarColor: topBarColorInput.value,
  211. textColor: textColorInput.value // No topBarIconsColor
  212. };
  213.  
  214. const colorSchemeString = JSON.stringify(colorScheme);
  215.  
  216. // Copy to clipboard without a popup
  217. navigator.clipboard.writeText(colorSchemeString)
  218. .then(() => {
  219. console.log('Color scheme exported to clipboard successfully:', colorSchemeString);
  220. })
  221. .catch(err => {
  222. console.error('Failed to copy: ', err);
  223. });
  224. });
  225.  
  226. // Import color scheme from clipboard
  227. importButton.addEventListener('click', async () => {
  228. try {
  229. const text = await navigator.clipboard.readText();
  230. const colorScheme = JSON.parse(text);
  231.  
  232. // Apply the imported color values to the input fields
  233. backgroundColorInput.value = colorScheme.backgroundColor || '#202c3c';
  234. actionBarColorInput.value = colorScheme.actionBarColor || '#40444c';
  235. topBarColorInput.value = colorScheme.topBarColor || '#505c6c';
  236. textColorInput.value = colorScheme.textColor || '#ffffff';
  237.  
  238. // Update the UI with the imported values immediately
  239. const appElement = document.querySelector('#app[data-v-app]');
  240. if (appElement) {
  241. appElement.style.backgroundColor = backgroundColorInput.value;
  242. }
  243.  
  244. const actionBarElement = document.querySelector('#currentAction.shadow.shadow-slate-800');
  245. if (actionBarElement) {
  246. actionBarElement.style.backgroundColor = actionBarColorInput.value;
  247. }
  248.  
  249. const topBarElement = document.querySelector('nav.navbar.is-fixed-top.is-primary.shadow-sm.shadow-slate-800\\/50');
  250. if (topBarElement) {
  251. topBarElement.style.backgroundColor = topBarColorInput.value;
  252. }
  253.  
  254. // Apply text color to body and other elements
  255. document.body.style.color = textColorInput.value;
  256. applyTextColorToAll(textColorInput.value); // Apply to all relevant elements
  257.  
  258. } catch (error) {
  259. console.error('Import error: ', error);
  260. alert('Failed to import color scheme. Please ensure the clipboard has a valid format.');
  261. }
  262. });
  263. // Add UI container to the body
  264. document.body.appendChild(uiContainer);
  265.  
  266. // Set colors from localStorage when the script loads
  267. setColors();
  268.  
  269. // Change Background Color dynamically
  270. backgroundColorInput.addEventListener('input', () => {
  271. const appElement = document.querySelector('#app[data-v-app]');
  272. if (appElement) {
  273. appElement.style.backgroundColor = backgroundColorInput.value;
  274. }
  275. });
  276.  
  277. // Change Action Bar color dynamically
  278. actionBarColorInput.addEventListener('input', () => {
  279. const actionBarElement = document.querySelector('#currentAction.shadow.shadow-slate-800');
  280. if (actionBarElement) {
  281. actionBarElement.style.backgroundColor = actionBarColorInput.value;
  282. }
  283. });
  284.  
  285. // Change Top Bar color dynamically
  286. topBarColorInput.addEventListener('input', () => {
  287. const topBarElement = document.querySelector('nav.navbar.is-fixed-top.is-primary.shadow-sm.shadow-slate-800\\/50');
  288. if (topBarElement) {
  289. topBarElement.style.backgroundColor = topBarColorInput.value;
  290. }
  291. });
  292.  
  293. // Change Text Color dynamically
  294. textColorInput.addEventListener('input', () => {
  295. document.body.style.color = textColorInput.value; // Change body text color
  296. applyTextColorToAll(textColorInput.value); // Apply to all relevant elements
  297. });
  298.  
  299. // Save color changes to localStorage on button click
  300. saveButton.addEventListener('click', () => {
  301. const backgroundColor = backgroundColorInput.value;
  302. const actionBarColor = actionBarColorInput.value;
  303. const topBarColor = topBarColorInput.value;
  304. const textColor = textColorInput.value; // Get text color input value
  305.  
  306. localStorage.setItem('backgroundColor', backgroundColor); // Save to localStorage
  307. localStorage.setItem('actionBarColor', actionBarColor); // Save to localStorage
  308. localStorage.setItem('topBarColor', topBarColor); // Save to localStorage
  309. localStorage.setItem('textColor', textColor); // Save to localStorage
  310.  
  311. // Set colors again to ensure everything is updated
  312. setColors();
  313. });
  314.  
  315. // Reset button functionality
  316. resetButton.addEventListener('click', () => {
  317. localStorage.removeItem('backgroundColor');
  318. localStorage.removeItem('actionBarColor');
  319. localStorage.removeItem('topBarColor');
  320. localStorage.removeItem('textColor');
  321. setColors(); // Reset colors to defaults
  322. });
  323.  
  324. // Optional: Add basic styling for the UI
  325. GM_addStyle(`
  326. #colorChangerUI input[type="color"] {
  327. cursor: pointer;
  328. margin-left: 5px;
  329. }
  330. #colorChangerUI button {
  331. cursor: pointer;
  332. color: #fff;
  333. border: none;
  334. padding: 5px 10px;
  335. border-radius: 3px;
  336. font-size: 12px; /* Match font size to your requirements */
  337. }
  338. #colorChangerUI button:hover {
  339. opacity: 0.8; /* Slightly dim on hover */
  340. }
  341. #colorChangerUI button#saveButton {
  342. background-color: green; /* Green background for Save */
  343. }
  344. #colorChangerUI button#resetButton {
  345. background-color: red; /* Red background for Reset */
  346. }
  347. `);
  348.  
  349. // Change the button IDs for styling
  350. saveButton.id = 'saveButton'; // Add ID for Save button
  351. resetButton.id = 'resetButton'; // Add ID for Reset button
  352. // Function to observe and reapply colors when new elements are added
  353. function observePageChanges() {
  354. const observer = new MutationObserver((mutations) => {
  355. mutations.forEach((mutation) => {
  356. if (mutation.addedNodes.length) {
  357. setColors(); // Reapply colors when new nodes are added
  358. }
  359. });
  360. });
  361.  
  362. // Observe the entire document body for child additions
  363. observer.observe(document.body, { childList: true, subtree: true });
  364. }
  365.  
  366. // Start observing the page for changes
  367. observePageChanges();
  368. // Start waiting for elements to load
  369. waitForElements();
  370. })();