IdlePixel+ Zlef's Modal & Settings Manager

Modal framework for Idle-Pixel with a Settings manager, modal optional for settings

目前為 2024-07-10 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/500003/1408451/IdlePixel%2B%20Zlef%27s%20Modal%20%20Settings%20Manager.js

  1. // ==UserScript==
  2. // @name IdlePixel+ Zlef's Modal & Settings Manager
  3. // @namespace com.zlef.modallibrary
  4. // @version 1.0.1
  5. // @description Modal framework for Idle-Pixel with a Settings manager, modal optional for settings
  6. // @author Zlef
  7. // @match *://idle-pixel.com/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. if(window.ZlefsModal ) {
  16. return;
  17. }
  18.  
  19. class ZlefsModal {
  20. constructor(pluginName) {
  21. this.pluginName = pluginName;
  22. this.modals = [];
  23. this.overlay = null;
  24. this.closeCallbacks = [];
  25. this.initCustomCSS();
  26. console.log("banana");
  27. }
  28.  
  29. initCustomCSS() {
  30. const css = `
  31. .zlefs-modal {
  32. position: absolute;
  33. background-color: #fff;
  34. border-radius: 8px;
  35. box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
  36. top: 50%;
  37. left: 50%;
  38. transform: translate(-50%, -50%);
  39. max-height: 80vh;
  40. max-width: 80vh;
  41. display: flex;
  42. flex-direction: column;
  43. overflow: hidden; /* Ensures rounded corners are visible */
  44. }
  45. .zlefs-modal-header {
  46. cursor: move;
  47. padding-bottom: 40px;
  48. margin-bottom: 10px;
  49. background-color: #f1f1f1;
  50. border-bottom: 1px solid #ccc;
  51. position: sticky;
  52. top: 0;
  53. left: 0;
  54. right: 0;
  55. width: 100%;
  56. box-sizing: border-box;
  57. border-top-left-radius: 8px; /* Rounded corners */
  58. border-top-right-radius: 8px; /* Rounded corners */
  59. z-index: 10; /* Ensure header is above the content */
  60. }
  61. .zlefs-modal-header-text {
  62. position: absolute;
  63. top: 50%;
  64. left: 10px;
  65. transform: translateY(-50%);
  66. pointer-events: none;
  67. height: 20px;
  68. font-weight: bold;
  69. }
  70. .zlefs-modal-content {
  71. padding: 0 20px 20px 20px;
  72. overflow-y: auto;
  73. flex-grow: 1; /* Allows the content to grow and fill the remaining space */
  74. }
  75. .zlefs-close-button {
  76. position: absolute;
  77. top: 10px;
  78. right: 10px;
  79. background: none;
  80. border: none;
  81. cursor: pointer;
  82. z-index: 11; /* Ensure close button is above the header */
  83. }
  84. #zlefs-modal-overlay {
  85. position: fixed;
  86. top: 0;
  87. left: 0;
  88. width: 100%;
  89. height: 100%;
  90. background-color: rgba(0, 0, 0, 0.7);
  91. z-index: 1000;
  92. display: flex;
  93. justify-content: center;
  94. align-items: center;
  95. }
  96. .zlefs-section {
  97. border: 1px solid black;
  98. background-color: white;
  99. padding: 10px 10px 0px 10px;
  100. margin-bottom: 10px;
  101. }
  102. .zlefs-section-title {
  103. margin-bottom: 10px;
  104. margin-left: 2px;
  105. font-weight: bold;
  106. cursor: pointer;
  107. }
  108. .zlefs-section-content {
  109. display: none;
  110. }
  111. .zlefs-section-content.zlefs-hidden {
  112. display: block;
  113. }
  114. .zlefs-item {
  115. width: 100%;
  116. display: flex;
  117. justify-content: space-between;
  118. align-items: center;
  119. margin-bottom: 5px;
  120. }
  121. .zlefs-checkbox-container {
  122. display: flex;
  123. justify-content: space-between;
  124. align-items: center;
  125. width: 100%;
  126. max-width: 400px;
  127. }
  128. .zlefs-checkbox-label {
  129. flex: 1;
  130. text-align: left;
  131. margin-right: 10px;
  132. }
  133. .zlefs-checkbox-input {
  134. flex: 0;
  135. text-align: right;
  136. }
  137. .zlefs-vertical-divider {
  138. width: 1px;
  139. background-color: #ccc;
  140. padding: 0;
  141. display: flex;
  142. }
  143. `;
  144. const style = document.createElement('style');
  145. style.type = 'text/css';
  146. style.appendChild(document.createTextNode(css));
  147. document.head.appendChild(style);
  148. }
  149.  
  150. createOverlay() {
  151. if (this.overlay) return;
  152.  
  153. this.overlay = document.createElement('div');
  154. this.overlay.id = 'zlefs-modal-overlay';
  155.  
  156. this.overlay.addEventListener('click', (event) => {
  157. if (event.target === this.overlay) {
  158. this.closeTopModal();
  159. }
  160. });
  161.  
  162. document.body.appendChild(this.overlay);
  163. }
  164.  
  165. addModal(content, name, width = 'auto', height = 'auto', closeCallback = null) {
  166. this.createOverlay();
  167.  
  168. const modalBox = document.createElement('div');
  169. modalBox.className = 'zlefs-modal';
  170. modalBox.style.width = typeof width === 'number' ? `${width}px` : width;
  171. modalBox.style.height = typeof height === 'number' ? `${height}px` : height;
  172.  
  173. const closeButton = document.createElement('button');
  174. closeButton.className = 'zlefs-close-button';
  175. closeButton.textContent = '✖';
  176. closeButton.addEventListener('click', () => {
  177. this.closeModal(modalBox);
  178. if (closeCallback) closeCallback();
  179. });
  180.  
  181. const header = document.createElement('div');
  182. header.className = 'zlefs-modal-header';
  183.  
  184. const nameSpan = document.createElement('span');
  185. nameSpan.textContent = name;
  186. nameSpan.className = 'zlefs-modal-header-text';
  187.  
  188. header.appendChild(nameSpan);
  189.  
  190. const contentWrapper = document.createElement('div');
  191. contentWrapper.className = 'zlefs-modal-content';
  192. contentWrapper.appendChild(content);
  193.  
  194. modalBox.appendChild(header);
  195. modalBox.appendChild(closeButton);
  196. modalBox.appendChild(contentWrapper);
  197. this.overlay.appendChild(modalBox);
  198. this.modals.push(modalBox);
  199. this.closeCallbacks.push(closeCallback);
  200.  
  201. this.makeDraggable(modalBox, header);
  202.  
  203. // Ensure modal is fully rendered before centering
  204. setTimeout(() => {
  205. this.centreModal(modalBox);
  206. }, 0);
  207. }
  208.  
  209. centreModal(modalBox) {
  210. if (!modalBox) {
  211. console.log("modalBox is not defined. If you're seeing this good luck lol.");
  212. return;
  213. }
  214. const rect = modalBox.getBoundingClientRect();
  215.  
  216. // Window dimensions
  217. // const windowWidth = window.innerWidth;
  218. const windowHeight = window.innerHeight;
  219.  
  220. const newModalTop = (windowHeight - rect.height) / 2
  221.  
  222. modalBox.style.top = `${newModalTop}px`;
  223. // Set min width as moving the modal against the side can squish it. Should probably solve that behaviour instead but here we are.
  224. modalBox.style.minWidth = `${rect.width}px`;
  225. }
  226.  
  227. closeModal(modal) {
  228. const modalIndex = this.modals.indexOf(modal);
  229. if (modalIndex !== -1) {
  230. this.modals.splice(modalIndex, 1);
  231. this.closeCallbacks.splice(modalIndex, 1);
  232. }
  233. if (modal && modal.parentElement) {
  234. this.overlay.removeChild(modal);
  235. }
  236. if (this.modals.length === 0 && this.overlay) {
  237. document.body.removeChild(this.overlay);
  238. this.overlay = null;
  239. }
  240. }
  241.  
  242. closeTopModal() {
  243. if (this.modals.length > 0) {
  244. const topmodal = this.modals[this.modals.length - 1];
  245. const topCallback = this.closeCallbacks[this.closeCallbacks.length - 1];
  246. this.closeModal(topmodal);
  247. if (topCallback) topCallback();
  248. }
  249. }
  250.  
  251. makeDraggable(modalBox, header) {
  252. let offsetX = 0, offsetY = 0, startX = 0, startY = 0;
  253.  
  254. const onMouseDown = (e) => {
  255. e.preventDefault();
  256.  
  257. startX = e.clientX;
  258. startY = e.clientY;
  259.  
  260. offsetX = modalBox.offsetLeft;
  261. offsetY = modalBox.offsetTop;
  262. document.addEventListener('mousemove', onMouseMove);
  263. document.addEventListener('mouseup', onMouseUp);
  264. };
  265.  
  266. const onMouseMove = (e) => {
  267. e.preventDefault();
  268. let dx = e.clientX - startX;
  269. let dy = e.clientY - startY;
  270.  
  271. let newLeft = offsetX + dx;
  272. let newTop = offsetY + dy;
  273.  
  274. modalBox.style.left = `${newLeft}px`;
  275. modalBox.style.top = `${newTop}px`;
  276. };
  277.  
  278. const onMouseUp = (e) => {
  279. const rect = modalBox.getBoundingClientRect();
  280. const corners = {
  281. topLeft: { left: rect.left, top: rect.top },
  282. bottomRight: { left: rect.right, top: rect.bottom }
  283. };
  284.  
  285. if (rect.left < 0) {
  286. modalBox.style.left = (rect.width/2) + 'px';
  287. }
  288. if (rect.top < 0) {
  289. modalBox.style.top = (rect.height/2) + 'px';
  290. }
  291. if (rect.right > window.innerWidth) {
  292. modalBox.style.left = (window.innerWidth - (rect.width/2)) + 'px';
  293. }
  294. if (rect.bottom > window.innerHeight) {
  295. modalBox.style.top = (window.innerHeight - (rect.height/2)) + 'px';
  296. }
  297.  
  298. document.removeEventListener('mousemove', onMouseMove);
  299. document.removeEventListener('mouseup', onMouseUp);
  300. };
  301.  
  302.  
  303. header.addEventListener('mousedown', onMouseDown);
  304. }
  305.  
  306. repositionmodal(modalBox) {
  307. if (!modalBox) return;
  308.  
  309. const rect = modalBox.getBoundingClientRect();
  310. const corners = {
  311. topLeft: { left: rect.left, top: rect.top },
  312. bottomRight: { left: rect.right, top: rect.bottom }
  313. };
  314.  
  315. if (rect.left < 0) {
  316. modalBox.style.left = (rect.width / 2) + 'px';
  317. }
  318. if (rect.top < 0) {
  319. modalBox.style.top = (rect.height / 2) + 'px';
  320. }
  321. if (rect.right > window.innerWidth) {
  322. modalBox.style.left = (window.innerWidth - (rect.width / 2)) + 'px';
  323. }
  324. if (rect.bottom > window.innerHeight) {
  325. modalBox.style.top = (window.innerHeight - (rect.height / 2)) + 'px';
  326. }
  327. }
  328.  
  329. titleCaseUnderscore(input) {
  330. const words = input.split('_');
  331. const convertedText = words.map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
  332. return convertedText;
  333. }
  334.  
  335. addTitle(parent, text, level = 2, textAlign = 'left') {
  336. const title = document.createElement(`h${level}`);
  337. title.textContent = text;
  338. title.style.textAlign = textAlign;
  339. parent.appendChild(title);
  340. return title
  341. }
  342.  
  343. addSection(parent, sectionTitleText) {
  344. const sectionDiv = document.createElement('div');
  345. sectionDiv.className = 'zlefs-section';
  346.  
  347. const sectionTitle = document.createElement('div');
  348. sectionTitle.className = 'zlefs-section-title';
  349. sectionTitle.textContent = sectionTitleText;
  350.  
  351. const sectionContent = document.createElement('div');
  352. sectionContent.className = 'zlefs-section-content';
  353.  
  354. sectionTitle.addEventListener('click', () => {
  355. const modal = this.findParentmodal(sectionDiv);
  356.  
  357. const originalTop = modal.getBoundingClientRect().top;
  358. const originalScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
  359.  
  360. sectionContent.classList.toggle('zlefs-hidden');
  361.  
  362. const newTop = modal.getBoundingClientRect().top;
  363. const deltaHeight = parseInt((originalTop - newTop));
  364.  
  365. const currentTop = parseInt(window.getComputedStyle(modal).top);
  366. modal.style.top = `${(currentTop + deltaHeight)}px`;
  367.  
  368. this.repositionmodal(modal);
  369.  
  370. });
  371.  
  372. sectionDiv.appendChild(sectionTitle);
  373. sectionDiv.appendChild(sectionContent);
  374. parent.appendChild(sectionDiv);
  375.  
  376. return sectionContent;
  377. }
  378.  
  379. findParentmodal(element) {
  380. while (element && !element.classList.contains('zlefs-modal')) {
  381. element = element.parentElement;
  382. }
  383. return element;
  384. }
  385.  
  386. addDiv(parent) {
  387. const div = document.createElement('div');
  388. parent.appendChild(div);
  389. return div;
  390. }
  391.  
  392. addContainer(parent) {
  393. const container = document.createElement('div');
  394. container.className = 'container';
  395. parent.appendChild(container);
  396. return container;
  397. }
  398.  
  399. addRow(parent) {
  400. const row = document.createElement('div');
  401. row.className = 'row';
  402. parent.appendChild(row);
  403. return row;
  404. }
  405.  
  406. addCol(parent, size = '', align = 'left') {
  407. const col = document.createElement('div');
  408. col.className = size ? `col-${size}` : 'col';
  409. col.style.textAlign = align === 'centre' ? 'center' : align;
  410. parent.appendChild(col);
  411. return col;
  412. }
  413.  
  414. addDivider(parent, margin = 5) {
  415. const divider = document.createElement('hr');
  416. divider.style.width = `calc(100% - ${2 * margin}px)`;
  417. divider.style.marginLeft = `${margin}px`;
  418. divider.style.marginRight = `${margin}px`;
  419. parent.appendChild(divider);
  420. return divider;
  421. }
  422.  
  423. addVDivider(parent) {
  424. const divider = document.createElement('div');
  425. divider.className = 'zlefs-vertical-divider';
  426. parent.appendChild(divider);
  427. }
  428.  
  429. addInput(parent, type, value, placeholder, min, max, onChange, label = undefined) {
  430. const inputContainer = document.createElement('div');
  431. inputContainer.style.display = 'flex';
  432. inputContainer.style.alignItems = 'center';
  433. inputContainer.style.marginBottom = '10px';
  434.  
  435. if (label){
  436. const inputLabel = document.createElement('label');
  437. inputLabel.textContent = this.titleCaseUnderscore(label);
  438. inputLabel.style.marginRight = '10px';
  439. inputLabel.style.flex = '1';
  440. inputLabel.style.cursor = 'pointer';
  441. inputContainer.appendChild(inputLabel);
  442. }
  443.  
  444. const input = document.createElement('input');
  445. input.type = type;
  446. input.value = value;
  447. input.style.flex = '0';
  448. if (placeholder) input.placeholder = placeholder;
  449. if (min !== undefined) input.min = min;
  450. if (max !== undefined) input.max = max;
  451. input.addEventListener('input', (event) => {
  452. let inputValue = event.target.value;
  453. if (type === 'number') {
  454. if (inputValue < min) inputValue = min;
  455. if (inputValue > max) inputValue = max;
  456. event.target.value = inputValue;
  457. }
  458. onChange(inputValue);
  459. });
  460.  
  461. inputContainer.appendChild(input);
  462. parent.appendChild(inputContainer);
  463. }
  464.  
  465. addCheckbox(parent, checked, onChange, label = undefined) {
  466. const checkboxContainer = document.createElement('div');
  467. checkboxContainer.className = 'zlefs-checkbox-container';
  468. checkboxContainer.style.display = 'flex';
  469. checkboxContainer.style.alignItems = 'center';
  470. checkboxContainer.style.marginBottom = '10px';
  471.  
  472. const checkbox = document.createElement('input');
  473. checkbox.type = 'checkbox';
  474. checkbox.checked = checked;
  475. checkbox.className = 'zlefs-checkbox-input';
  476. checkbox.style.flex = '0';
  477. checkbox.style.cursor = 'pointer';
  478. checkbox.addEventListener('change', (event) => onChange(event.target.checked));
  479.  
  480.  
  481. if (label){
  482. const checkboxLabel = document.createElement('label');
  483. checkboxLabel.textContent = this.titleCaseUnderscore(label);
  484. checkboxLabel.className = 'zlefs-checkbox-label';
  485. checkboxLabel.style.flex = '1';
  486. checkboxLabel.style.cursor = 'pointer';
  487.  
  488. checkboxContainer.appendChild(checkboxLabel);
  489. checkboxLabel.addEventListener('click', () => checkbox.click());
  490. }
  491.  
  492. checkboxContainer.appendChild(checkbox);
  493. parent.appendChild(checkboxContainer);
  494. }
  495.  
  496. addButton(parent, text, onClick, className = 'btn') {
  497. const button = document.createElement('button');
  498. button.textContent = text;
  499. button.className = className;
  500. button.addEventListener('click', onClick);
  501. parent.appendChild(button);
  502. return button;
  503. }
  504.  
  505. addCombobox(parent, options, selectedValue, onChange, label = undefined) {
  506. const comboboxContainer = document.createElement('div');
  507. comboboxContainer.style.display = 'flex';
  508. comboboxContainer.style.alignItems = 'center';
  509. comboboxContainer.style.marginBottom = '10px';
  510.  
  511. if (label) {
  512. const comboboxLabel = document.createElement('label');
  513. comboboxLabel.textContent = this.titleCaseUnderscore(label);
  514. comboboxLabel.style.marginRight = '10px';
  515. comboboxLabel.style.flex = '1';
  516. comboboxLabel.style.cursor = 'pointer';
  517. comboboxContainer.appendChild(comboboxLabel);
  518. }
  519.  
  520. const combobox = document.createElement('select');
  521. combobox.style.flex = '0';
  522. options.forEach(option => {
  523. const optionElement = document.createElement('option');
  524. optionElement.value = option;
  525. optionElement.text = option;
  526. if (option === selectedValue) optionElement.selected = true;
  527. combobox.appendChild(optionElement);
  528. });
  529.  
  530. combobox.addEventListener('change', (event) => onChange(event.target.value));
  531.  
  532. comboboxContainer.appendChild(combobox);
  533. parent.appendChild(comboboxContainer);
  534. return comboboxContainer;
  535. }
  536. }
  537.  
  538. class ZlefsSettingsManager {
  539. constructor(prefix, settings) {
  540. this.prefix = prefix;
  541. this.defaultSettings = JSON.parse(JSON.stringify(settings));
  542. this.settings = settings;
  543. this.modalContent = null;
  544. this.loadSettings();
  545. }
  546.  
  547. saveSettings() {
  548. const settingsToSave = {};
  549.  
  550. const processSettings = (settings, saveObj) => {
  551. for (const key in settings) {
  552. const setting = settings[key];
  553. if (setting.type === 'button') {
  554. continue; // Skip button types
  555. }
  556. if (setting.type === 'section') {
  557. saveObj[key] = {
  558. type: 'section',
  559. name: setting.name,
  560. settings: {}
  561. };
  562. processSettings(setting.settings, saveObj[key].settings);
  563. } else if (setting.type === 'multicheckbox') {
  564. saveObj[key] = {
  565. type: 'multicheckbox',
  566. values: {}
  567. };
  568. for (const subKey in setting.values) {
  569. saveObj[key].values[subKey] = setting.values[subKey];
  570. }
  571. } else if (setting.type === 'combobox') {
  572. saveObj[key] = {
  573. type: 'combobox',
  574. options: setting.options,
  575. value: setting.value
  576. };
  577. } else {
  578. saveObj[key] = {
  579. type: setting.type,
  580. value: setting.value
  581. };
  582. }
  583. }
  584. };
  585.  
  586. processSettings(this.settings, settingsToSave);
  587. localStorage.setItem(`${this.prefix}_settings`, JSON.stringify(settingsToSave));
  588. }
  589.  
  590. loadSettings() {
  591. const savedSettings = JSON.parse(localStorage.getItem(`${this.prefix}_settings`));
  592. if (savedSettings) {
  593. const processLoadedSettings = (loadedSettings, currentSettings) => {
  594. for (const key in currentSettings) {
  595. if (loadedSettings[key] !== undefined) {
  596. const setting = currentSettings[key];
  597. if (setting.type === 'button') {
  598. continue; // Skip button types
  599. }
  600. if (setting.type === 'section') {
  601. processLoadedSettings(loadedSettings[key].settings, setting.settings);
  602. } else if (setting.type === 'multicheckbox') {
  603. for (const subKey in setting.values) {
  604. setting.values[subKey] = loadedSettings[key].values[subKey] !== undefined
  605. ? loadedSettings[key].values[subKey]
  606. : setting.values[subKey];
  607. }
  608. } else {
  609. setting.value = loadedSettings[key].value;
  610. }
  611. }
  612. }
  613.  
  614. for (const key in loadedSettings) {
  615. if (currentSettings[key] === undefined) {
  616. delete loadedSettings[key];
  617. }
  618. }
  619. };
  620.  
  621. processLoadedSettings(savedSettings, this.settings);
  622. localStorage.setItem(`${this.prefix}_settings`, JSON.stringify(this.settings));
  623. }
  624. }
  625.  
  626. resetSettings() {
  627. this.settings = JSON.parse(JSON.stringify(this.defaultSettings));
  628. this.saveSettings();
  629. }
  630.  
  631. deleteSettings() {
  632. localStorage.removeItem(`${this.prefix}_settings`);
  633. }
  634.  
  635. getSettings() {
  636. return this.settings;
  637. }
  638.  
  639. settingsChanged(fullKey, value, subKey = null) {
  640. const keys = fullKey.split('.');
  641. let currentSettings = this.settings;
  642.  
  643. for (let i = 0; i < keys.length - 1; i++) {
  644. if (currentSettings[keys[i]].type === 'section') {
  645. currentSettings = currentSettings[keys[i]].settings;
  646. } else if (currentSettings[keys[i]].type === 'multicheckbox' && subKey) {
  647. currentSettings = currentSettings[keys[i]].values;
  648. } else {
  649. currentSettings = currentSettings[keys[i]];
  650. }
  651. }
  652.  
  653. const finalKey = keys[keys.length - 1];
  654.  
  655. if (!currentSettings[finalKey]) {
  656. console.error(`settingsChanged - Key ${finalKey} not found in settings`);
  657. return;
  658. }
  659.  
  660. if (subKey) {
  661. currentSettings[finalKey].values[subKey] = value;
  662. } else {
  663. currentSettings[finalKey].value = value;
  664. }
  665. this.saveSettings();
  666. }
  667.  
  668. createSettingsModal(modalFramework, width = 'auto', height = 'auto', closeCallback = null) {
  669. return () => {
  670. const content = document.createElement('div');
  671.  
  672. const buildSettings = (settings, parent) => {
  673. if (!parent) {
  674. console.error('Parent element is null');
  675. return;
  676. }
  677.  
  678. for (const key in settings) {
  679. const setting = settings[key];
  680. const fullKey = key;
  681.  
  682. if (setting.type === 'section') {
  683. const sectionContent = modalFramework.addSection(parent, setting.name);
  684. buildSettings(setting.settings, sectionContent);
  685. } else if (setting.type === 'multicheckbox') {
  686. const sectionContent = modalFramework.addSection(parent, setting.name);
  687. for (const subKey in setting.values) {
  688. modalFramework.addCheckbox(sectionContent, setting.values[subKey], (value) => {
  689. this.settingsChanged(`${fullKey}.${subKey}`, value, subKey);
  690. }, subKey);
  691. }
  692. } else if (setting.type === 'checkbox') {
  693. modalFramework.addCheckbox(parent, setting.value, (value) => {
  694. this.settingsChanged(fullKey, value);
  695. }, key);
  696. } else if (setting.type === 'numinput') {
  697. modalFramework.addInput(parent, 'number', setting.value, '', setting.minValue, setting.maxValue, (value) => {
  698. this.settingsChanged(fullKey, value);
  699. }, key);
  700. } else if (setting.type === 'text') {
  701. modalFramework.addInput(parent, 'text', setting.value, setting.placeholder, undefined, undefined, (value) => {
  702. this.settingsChanged(fullKey, value);
  703. }, key);
  704. } else if (setting.type === 'combobox') {
  705. modalFramework.addCombobox(parent, setting.options, setting.value, (value) => {
  706. this.settingsChanged(fullKey, value);
  707. }, key);
  708. } else if (setting.type === 'button') {
  709. modalFramework.addButton(parent, setting.name, setting.function, 'btn');
  710. }
  711. }
  712. };
  713.  
  714. buildSettings(this.settings, content);
  715.  
  716. modalFramework.addModal(content, `${this.prefix} Settings`, width, height, closeCallback);
  717. };
  718. }
  719.  
  720. }
  721.  
  722. window.ZlefsModal = ZlefsModal;
  723. window.ZlefsSettingsManager = ZlefsSettingsManager;
  724. })();

QingJ © 2025

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