gz-component

一个常用的组件库

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/524094/1522518/gz-component.js

  1. // ==UserScript==
  2. // @name gz-component
  3. // @namespace http://tampermonkey.net/
  4. // @license Apache-2.0
  5. // @version 1.0.1
  6. // @author byhgz
  7. // @description 一个常用的组件库
  8. // @noframes
  9. // ==/UserScript==
  10. "use strict";
  11. (function () {
  12. 'use strict';
  13. class SheetDialog {
  14. #div;
  15. #shadowRoot;
  16. #config;
  17. #isInsertIntoBody;
  18. #optionEvent;
  19. constructor(config) {
  20. this.#config = config;
  21. const div = document.createElement('div');
  22. div.attachShadow({mode: 'open'});
  23. div.shadowRoot.innerHTML = `
  24. <style>
  25. .sheet-dialog-overlay {
  26. position: fixed;
  27. top: 0;
  28. left: 0;
  29. width: 100%;
  30. height: 100%;
  31. background-color: rgba(0, 0, 0, 0.5);
  32. display: flex;
  33. justify-content: center;
  34. align-items: center;
  35. z-index: 1000;
  36. }
  37. .sheet-dialog-content {
  38. background-color: white;
  39. border-radius: 8px;
  40. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  41. padding: 20px;
  42. max-height: 90vh;
  43. overflow-y: auto;
  44. width: 300px;
  45. z-index: 1001;
  46. }
  47. .sheet-dialog-header {
  48. font-size: 18px;
  49. margin-bottom: 10px;
  50. }
  51. .sheet-dialog-options button {
  52. display: block;
  53. width: 100%;
  54. padding: 10px;
  55. margin-bottom: 5px;
  56. text-align: left;
  57. cursor: pointer;
  58. border: none;
  59. background: none;
  60. outline: none;
  61. transition: background-color 0.3s;
  62. }
  63. .sheet-dialog-options button:hover {
  64. background-color: #f0f0f0;
  65. }
  66. </style>
  67. <!-- 对话框整体结构 -->
  68. <div class="sheet-dialog-overlay">
  69. <div class="sheet-dialog-content">
  70. <div class="sheet-dialog-header"></div>
  71. <div class="sheet-dialog-options"></div>
  72. </div>
  73. </div>
  74. `;
  75. this.#div = div;
  76. this.#shadowRoot = div.shadowRoot;
  77. this.#init();
  78. }
  79. #init() {
  80. const config = this.#config;
  81. config.title = config.title || '';
  82. config.options = config.options || [];
  83. config.closeOnOverlayClick = config.closeOnOverlayClick !== false;
  84. this.#render();
  85. if (config.closeOnOverlayClick) {
  86. this.#shadowRoot.querySelector('.sheet-dialog-overlay').addEventListener('click', () => this.destroy());
  87. }
  88. this.#shadowRoot.querySelector('.sheet-dialog-content').addEventListener('click', event => event.stopPropagation());
  89. const tempIs = config['isInsertIntoBody'];
  90. if (tempIs || tempIs === undefined) {
  91. this.addBody();
  92. this.#isInsertIntoBody = true;
  93. }
  94. const optionEvent = config['optionEvent'];
  95. if (optionEvent) {
  96. this.setOptionEvent(optionEvent);
  97. } else {
  98. this.setOptionEvent((event) => {
  99. console.log('默认事件', event);
  100. });
  101. }
  102. }
  103. #render() {
  104. this.#shadowRoot.querySelector('.sheet-dialog-header').textContent = this.#config.title;
  105. const optionsContainer = this.#shadowRoot.querySelector('.sheet-dialog-options');
  106. for (const option of this.#config.options) {
  107. const button = document.createElement('button');
  108. if (typeof option === 'string') {
  109. button.textContent = option;
  110. } else {
  111. for (let key in option) {
  112. if (key === 'label') continue
  113. if (key === 'event' && typeof option['event'] === 'function') {
  114. continue
  115. }
  116. button.setAttribute(key, option[key]);
  117. }
  118. if (option['event']) {
  119. button.addEventListener('click', (event) => {
  120. const target = event.target;
  121. if (target.tagName !== 'BUTTON') {
  122. event.stopPropagation();
  123. event.preventDefault();
  124. return
  125. }
  126. if (option['event'](event, this.#getOptionAttrs(target), this) === true) {
  127. event.stopPropagation();
  128. event.preventDefault();
  129. }
  130. });
  131. }
  132. button.textContent = option.label || '默认label';
  133. }
  134. optionsContainer.appendChild(button);
  135. }
  136. optionsContainer.addEventListener('click', (event) => {
  137. const target = event.target;
  138. if (target.tagName !== 'BUTTON') {
  139. event.stopPropagation();
  140. event.preventDefault();
  141. return
  142. }
  143. if (this.#optionEvent(event, this.#getOptionAttrs(target), this)) {
  144. this.destroy();
  145. }
  146. });
  147. }
  148. #getOptionAttrs(target) {
  149. const attrNames = target.getAttributeNames();
  150. const attrs = [];
  151. for (let attrName of attrNames) {
  152. const val = target.getAttribute(attrName).trim();
  153. attrs.push({name: attrName, value: val});
  154. }
  155. return attrs
  156. }
  157. getAllOptionAttrs() {
  158. const optionsContainer = this.#shadowRoot.querySelector('.sheet-dialog-options');
  159. const buttons = optionsContainer.querySelectorAll('button');
  160. const attrs = [];
  161. for (let button of buttons) {
  162. const optionAttrs = this.#getOptionAttrs(button);
  163. attrs.push(...optionAttrs);
  164. }
  165. return attrs
  166. }
  167. setOptionEvent(callback) {
  168. this.#optionEvent = callback;
  169. }
  170. destroy() {
  171. this.#div.remove();
  172. }
  173. addBody() {
  174. if (this.#isInsertIntoBody) {
  175. return
  176. }
  177. this.#isInsertIntoBody = true;
  178. document.body.appendChild(this.#div);
  179. }
  180. }
  181. const gz = {
  182. version: '1.0.0',
  183. SheetDialog
  184. };
  185. window.gz = gz;
  186. })();

QingJ © 2025

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