GC - Universal Userscripts Settings

Library for adding a user interface to manage settings for grundos.cafe userscripts

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

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/514423/1473257/GC%20-%20Universal%20Userscripts%20Settings.js

  1. async function addTextInput(configuration) {
  2. let {
  3. categoryName,
  4. settingName,
  5. labelText,
  6. currentSetting = undefined,
  7. defaultSetting = '',
  8. callbackFunction = undefined
  9. } = configuration;
  10. const header = await _addCategoryHeader(categoryName);
  11. if (currentSetting === undefined) {
  12. currentSetting = await GM.getValue(settingName, defaultSetting);
  13. }
  14.  
  15. const textInput = document.createElement('input');
  16. textInput.type = 'text';
  17. textInput.name = settingName;
  18. textInput.value = currentSetting;
  19. const label = _createLabel(labelText);
  20. _addBelowHeader(header, label);
  21.  
  22. const inputElement = _createInput(textInput);
  23. label.insertAdjacentElement('afterend', inputElement);
  24.  
  25. if (callbackFunction) {
  26. _addCallback(() => callbackFunction(settingName, textInput.value));
  27. } else {
  28. _addCallback(async () => await GM.setValue(settingName, checkbox.checked));
  29. }
  30. }
  31.  
  32. async function addNumberInput(configuration) {
  33. let {
  34. categoryName,
  35. settingName,
  36. labelText,
  37. min = 0,
  38. max = 100,
  39. step = 1,
  40. currentSetting = undefined,
  41. defaultSetting = 0,
  42. callbackFunction = undefined
  43. } = configuration;
  44.  
  45. const header = await _addCategoryHeader(categoryName);
  46. if (currentSetting === undefined) {
  47. currentSetting = await GM.getValue(settingName, defaultSetting);
  48. }
  49.  
  50. const numberInput = document.createElement('input');
  51. numberInput.type = 'number';
  52. numberInput.name = settingName;
  53. numberInput.value = currentSetting;
  54. numberInput.min = min;
  55. numberInput.max = max;
  56. numberInput.step = step;
  57. const label = _createLabel(labelText);
  58. _addBelowHeader(header, label);
  59.  
  60. const inputElement = _createInput(numberInput);
  61. label.insertAdjacentElement('afterend', inputElement);
  62.  
  63. if (callbackFunction) {
  64. _addCallback(() => callbackFunction(settingName, numberInput.value));
  65. } else {
  66. _addCallback(async () => await GM.setValue(settingName, checkbox.checked));
  67. }
  68. }
  69.  
  70. async function addCheckboxInput(configuration) {
  71. let {
  72. categoryName,
  73. settingName,
  74. labelText,
  75. currentSetting = undefined,
  76. defaultSetting = false,
  77. callbackFunction = undefined
  78. } = configuration;
  79. const header = await _addCategoryHeader(categoryName);
  80. if (currentSetting === undefined) {
  81. currentSetting = await GM.getValue(settingName, defaultSetting);
  82. }
  83.  
  84. const checkbox = document.createElement('input');
  85. checkbox.type = 'checkbox';
  86. checkbox.name = settingName;
  87. checkbox.checked = currentSetting;
  88. const label = _createLabel(labelText);
  89. _addBelowHeader(header, label);
  90.  
  91. const inputElement = _createInput(checkbox);
  92. label.insertAdjacentElement('afterend', inputElement);
  93.  
  94. if (callbackFunction) {
  95. _addCallback(() => callbackFunction(settingName, checkbox.checked));
  96. } else {
  97. _addCallback(async () => await GM.setValue(settingName, checkbox.checked));
  98. }
  99. }
  100.  
  101. async function addDropdown(configuration) {
  102. let {
  103. categoryName,
  104. settingName,
  105. labelText,
  106. options, // [{ value: 'value', text: 'text', ... }]
  107. currentSetting = undefined,
  108. defaultSetting = undefined,
  109. callbackFunction = undefined
  110. } = configuration;
  111.  
  112. const header = await _addCategoryHeader(categoryName);
  113. if (currentSetting === undefined) {
  114. currentSetting = await GM.getValue(settingName, defaultSetting);
  115. }
  116.  
  117. const select = document.createElement('select');
  118. select.name = settingName;
  119. select.classList.add('form-control');
  120.  
  121. options.forEach(option => {
  122. const optionElement = document.createElement('option');
  123. optionElement.value = option.value;
  124. optionElement.textContent = option.text;
  125. if (option.value === currentSetting) {
  126. optionElement.selected = true;
  127. }
  128. select.appendChild(optionElement);
  129. });
  130. const label = _createLabel(labelText);
  131. _addBelowHeader(header, label);
  132.  
  133. const inputElement = _createInput(select);
  134. label.insertAdjacentElement('afterend', inputElement);
  135.  
  136. if (callbackFunction) {
  137. _addCallback(() => callbackFunction(settingName, select.value));
  138. } else {
  139. _addCallback(async () => await GM.setValue(settingName, checkbox.checked));
  140. }
  141. }
  142.  
  143. function _addBelowHeader(header, label) {
  144. let nextHeader = header.nextElementSibling;
  145. console.log("here");
  146. while (nextHeader && !nextHeader.matches('.header')) {
  147. nextHeader = nextHeader.nextElementSibling;
  148. }
  149. if (!nextHeader) {
  150. nextHeader = document.querySelector('#universal-userscript-preferences>.market_grid.profile.prefs.margin-auto>.footer.small-gap');
  151. }
  152. nextHeader.insertAdjacentElement('beforebegin', label);
  153. }
  154.  
  155. function _addSettingsLink() {
  156. const existingNav = document.querySelector('nav.center.margin-1');
  157. if (existingNav) {
  158. const newNav = document.createElement('nav');
  159. newNav.classList.add('center', 'margin-1');
  160. newNav.id = 'universal-userscript-navigation';
  161. const newLink = document.createElement('a');
  162. newLink.href = '/help/userscripts/';
  163. newLink.textContent = 'Userscript Preferences';
  164. newNav.appendChild(newLink);
  165. existingNav.after(newNav);
  166. } else {
  167. console.error('Existing navigation element not found.');
  168. }
  169. }
  170.  
  171. function _createLabel(labelText) {
  172. const labelContainer = document.createElement('div');
  173. labelContainer.classList.add('data', 'left');
  174.  
  175. const label = document.createElement('span');
  176. label.textContent = labelText;
  177. labelContainer.appendChild(label);
  178. return labelContainer;
  179. }
  180.  
  181. function _createInput(input) {
  182. const inputContainer = document.createElement('div');
  183. inputContainer.classList.add('data', 'flex-column', 'right');
  184. inputContainer.appendChild(input);
  185. return inputContainer;
  186. }
  187.  
  188. function _addCallback(callbackFunction) {
  189. document.getElementById('universal-userscript-update').addEventListener('click', callbackFunction);
  190. }
  191.  
  192. async function _addCategoryHeader(categoryName) {
  193. if (!window.location.href.includes('/help/userscripts/')) throw Error('Attempted to add setting outside of settings page.');
  194. await _checkSettingsSetup();
  195. const settings = document.querySelector('.market_grid.profile.prefs.margin-auto');
  196. const footer = document.querySelector('#universal-userscript-preferences>.market_grid.profile.prefs.margin-auto>.footer.small-gap');
  197. if (!settings) {
  198. console.error('Settings not found.');
  199. return;
  200. }
  201.  
  202. const headers = Array.from(settings.querySelectorAll('.header'));
  203. let header = headers.find(header => header.textContent.trim() === categoryName);
  204.  
  205. if (!header) {
  206. header = document.createElement('div');
  207. header.classList.add('header');
  208. header.innerHTML = `<strong>${categoryName}</strong>`;
  209. const insertionPoint = headers.find(existingHeader => existingHeader.textContent.trim().localeCompare(categoryName) > 0);
  210. if (insertionPoint) {
  211. insertionPoint.insertAdjacentElement('beforebegin', header);
  212. } else {
  213. footer.insertAdjacentElement('beforebegin', header);
  214. }
  215. }
  216.  
  217. return header;
  218. }
  219.  
  220. function _replaceBannerImage() {
  221. const bannerImage = document.getElementById('top-header-image');
  222. if (bannerImage) {
  223. bannerImage.src = 'https://grundoscafe.b-cdn.net/misc/banners/userinfo.gif';
  224. } else {
  225. console.error('Banner image not found.');
  226. }
  227. }
  228.  
  229. function _setupUniversalSettings() {
  230. const helpPages = /\/help\/(?:profile|siteprefs|sidebar|randomevents)\/|\/discord\//;
  231. const settings = window.location.href.includes('/help/userscripts/');
  232. const help = helpPages.test(window.location.href);
  233. if (help) {
  234. _addSettingsLink();
  235. } else if (settings) {
  236. _replaceBannerImage();
  237. const element = document.querySelector('main');
  238. if (element) {
  239. element.id = 'universal-userscript-preferences';
  240. element.innerHTML = `
  241. <h1>Userscript Preferences</h1>
  242. <nav class="center margin-1">
  243. <a href="/help/profile/">Edit Profile</a> |
  244. <a href="/help/siteprefs/">Site Preferences</a> |
  245. <a href="/help/sidebar/">Edit Sidebar</a> |
  246. <a href="/discord/">Discord</a> |
  247. <a href="/help/randomevents/">Random Event Log</a>
  248. </nav>
  249. <nav class="center margin-1" id="universal-userscript-navigation"><a href="/help/userscripts/">Userscript Preferences</a></nav>
  250. <p>Here you can adjust settings for participating userscripts.</p>
  251. <div class="market_grid profile prefs margin-auto">
  252. <div class="footer small-gap">
  253. <input class="form-control half-width" type="submit" value="Update Preferences" id="universal-userscript-update">
  254. </div>
  255. </div>
  256. `;
  257. }
  258. }
  259. }
  260.  
  261. async function _checkSettingsSetup() {
  262. return new Promise((resolve, reject) => {
  263. const interval = setInterval(() => {
  264. if (document.getElementById('universal-userscript-preferences') !== null) {
  265. clearInterval(interval);
  266. clearTimeout(timeout);
  267. resolve(true);
  268. }
  269. }, 50);
  270.  
  271. const timeout = setTimeout(() => {
  272. clearInterval(interval);
  273. reject(new Error('Timeout: universal-userscript-preferences element not found within 10 seconds'));
  274. }, 10000);
  275. });
  276. }
  277.  
  278. if (!document.getElementById('universal-userscript-navigation')) {
  279. _setupUniversalSettings();
  280. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址