🏠 Home 

Vanilla JS Dialog

A general purpose JavaScript class for Dialog Creation in Vanilla JS.

สคริปต์นี้ไม่ควรถูกติดตั้งโดยตรง มันเป็นคลังสำหรับสคริปต์อื่น ๆ เพื่อบรรจุด้วยคำสั่งเมทา // @require https://update.greasyfork.org/scripts/465421/1471180/Vanilla%20JS%20Dialog.js

  1. // ==UserScript==
  2. // @name Vanilla JS Dialog
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.2
  5. // @description A general purpose JavaScript class for Dialog Creation in Vanilla JS.
  6. // @author CY Fung
  7. // @grant none
  8. // @license MIT
  9. // ==/UserScript==
  10. /*
  11. MIT License
  12. Copyright (c) 2023 cyfung1031
  13. Permission is hereby granted, free of charge, to any person obtaining a copy
  14. of this software and associated documentation files (the "Software"), to deal
  15. in the Software without restriction, including without limitation the rights
  16. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  17. copies of the Software, and to permit persons to whom the Software is
  18. furnished to do so, subject to the following conditions:
  19. The above copyright notice and this permission notice shall be included in all
  20. copies or substantial portions of the Software.
  21. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  27. SOFTWARE.
  28. */
  29. /* version: 0.1.2 */
  30. const VanillaJSDialog = (function pluginVanillaJSDialog() {
  31. 'strict';
  32. const _themeProps_ = {
  33. dialogBackgroundColor: '#f6f6f6',
  34. dialogBackgroundColorDark: '#23252a',
  35. backdropColor: '#b5b5b568',
  36. textColor: '#343434',
  37. textColorDark: '#f0f3f4',
  38. zIndex: 60000,
  39. fontSize: '10pt',
  40. dialogMinWidth: '320px',
  41. dialogMinHeight: '240px',
  42. };
  43. /* https://www.freeformatter.com/css-beautifier.html */
  44. const _cssForThemeProps_ = ($) =>
  45. `
  46. .vjsd-dialog {
  47. --vjsd-font-family: "Inter var", ui-sans-serif, system-ui, -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  48. --vjsd-dialog-background-color: ${$.dialogBackgroundColor};
  49. --vjsd-dialog-text-color: ${$.textColor};
  50. --vjsd-dialog-border-color: #747474;
  51. --vjsd-inputable-background-color: #fcfcfc;
  52. --vjsd-inputable-text-color: ${$.textColor};
  53. --vjsd-inputable-outline-color: #959494;
  54. --vjsd-inputable-focus-outline-color: #212121;
  55. --vjsd-button-background-color: #FFFFFF;
  56. --vjsd-button-border-color: #959494;
  57. --vjsd-button-text-color: #111827;
  58. --vjsd-button-hover-background-color: rgb(249, 250, 251);
  59. --vjsd-button-hover-border-color: #212121;
  60. }
  61. .vjsd-dialog.vjsd-dark {
  62. --vjsd-dialog-background-color: ${$.dialogBackgroundColorDark};
  63. --vjsd-dialog-text-color: ${$.textColorDark};
  64. --vjsd-dialog-border-color: #878787;
  65. --vjsd-inputable-background-color: #181a1e;
  66. --vjsd-inputable-text-color: ${$.textColorDark};
  67. --vjsd-inputable-outline-color: #757576;
  68. --vjsd-inputable-focus-outline-color: #a7a5a5;
  69. --vjsd-button-background-color: #21262d;
  70. --vjsd-button-border-color: #6a6a6a;
  71. --vjsd-button-text-color: #c9d1d9;
  72. --vjsd-button-hover-background-color: #30363d;
  73. --vjsd-button-hover-border-color: #8b949e;
  74. }
  75. .vjsd-dialog * {
  76. overscroll-behavior: inherit;
  77. }
  78. .vjsd-overscroll-none {
  79. overscroll-behavior: none;
  80. }
  81. .vjsd-overscroll-contain {
  82. overscroll-behavior: contain;
  83. }
  84. .vjsd-overscroll-auto {
  85. overscroll-behavior: auto;
  86. }
  87. .vjsd-dialog {
  88. font-family: var(--vjsd-font-family);
  89. font-size: ${$.fontSize};
  90. display: none;
  91. flex-direction: column;
  92. position: fixed;
  93. pointer-events: all;
  94. top: 50%;
  95. left: 50%;
  96. transform: translate(-50%, -50%);
  97. z-index: ${$.zIndex};
  98. user-select: none;
  99. touch-action: none;
  100. border-radius: 12px;
  101. border: 1px solid var(--vjsd-dialog-border-color);
  102. box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  103. background-color: var(--vjsd-dialog-background-color);
  104. color: var(--vjsd-dialog-text-color);
  105. contain: content;
  106. }
  107. .vjsd-dialog textarea,
  108. .vjsd-dialog input {
  109. font-family: var(--vjsd-font-family);
  110. border: 0;
  111. outline: 1px solid var(--vjsd-inputable-outline-color);
  112. border-radius: 3px;
  113. -webkit-tap-highlight-color: rgba(0, 0, 0, 0.18) !important;
  114. overflow: auto;
  115. -webkit-box-shadow: none;
  116. -moz-box-shadow: none;
  117. box-shadow: none;
  118. resize: none;
  119. /* remove the resize handle on the bottom right */
  120. background-color: var(--vjsd-inputable-background-color);
  121. color: var(--vjsd-inputable-text-color);
  122. outline-color: var(--vjsd-inputable-outline-color);
  123. }
  124. .vjsd-dialog textarea:focus,
  125. .vjsd-dialog input:focus {
  126. outline-color: var(--vjsd-inputable-focus-outline-color);
  127. transition-duration: .1s;
  128. }
  129. .vjsd-title {
  130. padding: 4px 16px;
  131. text-decoration: none #D1D5DB solid;
  132. text-decoration-thickness: auto;
  133. font-weight: 700;
  134. letter-spacing: .6px;
  135. }
  136. .vjsd-dialog-visible {
  137. display: flex;
  138. }
  139. .vjsd-dialog-header {
  140. padding: 7px 12px;
  141. }
  142. .vjsd-dialog-body {
  143. padding: 7px 12px;
  144. }
  145. .vjsd-dialog-footer {
  146. padding: 7px 12px;
  147. }
  148. .vjsd-flex-fill {
  149. flex-grow: 1;
  150. }
  151. .vjsd-space {
  152. flex-grow: 1;
  153. }
  154. .vjsd-buttonicon {
  155. cursor: pointer;
  156. opacity: 0.85;
  157. }
  158. .vjsd-dialog-backdrop {
  159. background-color: ${$.backdropColor};
  160. contain: strict;
  161. }
  162. .vjsd-buttonicon:hover {
  163. opacity: 1.0;
  164. }
  165. .vjsd-icon {
  166. font-size: 180%;
  167. display: inline-flex;
  168. }
  169. .vjsd-button {
  170. display: inline-flex;
  171. background-color: var(--vjsd-button-background-color);
  172. border: 1px solid var(--vjsd-button-border-color);
  173. color: var(--vjsd-button-text-color);
  174. border-radius: .5em;
  175. box-sizing: border-box;
  176. font-family: var(--vjsd-font-family);
  177. font-size: 85%;
  178. font-weight: 600;
  179. padding: .66em .86em;
  180. text-align: center;
  181. text-decoration: none #D1D5DB solid;
  182. text-decoration-thickness: auto;
  183. box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  184. cursor: pointer;
  185. user-select: none;
  186. -webkit-user-select: none;
  187. touch-action: manipulation;
  188. }
  189. .vjsd-button:hover {
  190. background-color: var(--vjsd-button-hover-background-color);
  191. border-color: var(--vjsd-button-hover-border-color);
  192. transition-duration: .1s;
  193. }
  194. .vjsd-button:focus {
  195. outline: 2px solid transparent;
  196. outline-offset: 2px;
  197. }
  198. .vjsd-button:focus-visible {
  199. box-shadow: none;
  200. }
  201. .vjsd-vflex {
  202. display: flex;
  203. flex-direction: column;
  204. align-items: center;
  205. }
  206. .vjsd-dialog-footer.vjsd-hflex {
  207. column-gap: 8px;
  208. }
  209. .vjsd-hflex {
  210. display: flex;
  211. flex-direction: row;
  212. align-items: center;
  213. }
  214. .vjsd-dialog-backdrop {
  215. display: none;
  216. position: fixed;
  217. pointer-events: all;
  218. top: 0;
  219. bottom: 0;
  220. left: 0;
  221. right: 0;
  222. pointer-events: all;
  223. z-index: ${$.zIndex - 1};
  224. /* when modal active */
  225. touch-action: none;
  226. -webkit-overflow-scrolling: none;
  227. overflow: hidden;
  228. /* Other browsers */
  229. overscroll-behavior: none;
  230. }
  231. .vjsd-dialog-body {
  232. min-width: ${$.dialogMinWidth};
  233. min-height: ${$.dialogMinHeight};
  234. }
  235. .vjsd-dialog-body.vjsd-vflex {
  236. align-items: stretch;
  237. }
  238. .vjsd-dialog-backdrop.vjsd-backdrop-visible {
  239. display: flex;
  240. }
  241. label.vjsd-checkbox-label {
  242. font-weight: bold;
  243. line-height: 1.1;
  244. display: flex;
  245. flex-direction: row;
  246. gap: 0.5em;
  247. position: relative;
  248. z-index: 0;
  249. }
  250. label.vjsd-checkbox-label::after {
  251. /* avoid text seleciton */
  252. position: absolute;
  253. content: '';
  254. left: 0;
  255. top: 0;
  256. right: 0;
  257. bottom: 0;
  258. z-index: 1;
  259. }
  260. input.vjsd-checkbox1 {
  261. -webkit-appearance: none;
  262. appearance: none;
  263. /*background-color: var(--vjsd-dialog-background-color);*/
  264. margin: 0;
  265. font: inherit;
  266. color: currentColor;
  267. width: 1.15em;
  268. height: 1.15em;
  269. border: 0.15em solid currentColor;
  270. border-radius: 0.15em;
  271. transform: translateY(-0.075em);
  272. display: grid;
  273. place-content: center;
  274. outline: none;
  275. }
  276. input.vjsd-checkbox1::before {
  277. content: "";
  278. width: 0.65em;
  279. height: 0.65em;
  280. transform: scale(0);
  281. }
  282. input.vjsd-checkbox1:checked::before {
  283. transform: scale(1);
  284. }
  285. input.vjsd-checkbox-tick::before {
  286. transform-origin: bottom left;
  287. transition: 80ms transform ease-in-out;
  288. box-shadow: inset 1em 1em currentColor;
  289. background-color: CanvasText;
  290. clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
  291. }
  292. input.vjsd-checkbox-square::before {
  293. transition: 80ms transform ease-in-out;
  294. box-shadow: inset 1em 1em currentColor;
  295. border-radius: 4px;
  296. }
  297. input.vjsd-checkbox1.vjsd-checkbox-square:checked::before {
  298. transform: scale(0.9);
  299. }
  300. .vjsd-gap-1 {
  301. gap: 3px;
  302. }
  303. .vjsd-gap-2 {
  304. gap: 6px;
  305. }
  306. .vjsd-gap-3 {
  307. gap: 9px;
  308. }
  309. .vjsd-gap-4 {
  310. gap: 12px;
  311. }
  312. .vjsd-gap-5 {
  313. gap: 15px;
  314. }
  315. .sample-textbox {
  316. height: 300px;
  317. }
  318. html.vjsd-dialog-shown {
  319. --vjsd-prevent-scroll-pointer-events: none;
  320. --vjsd-prevent-scroll-overflow: hidden;
  321. }
  322. html,
  323. body {
  324. pointer-events: var(--vjsd-prevent-scroll-pointer-events) !important;
  325. overflow: var(--vjsd-prevent-scroll-overflow) !important;
  326. }
  327. html.vjsd-dialog-shown {
  328. --vjsd-page-background-filter: blur(4px);
  329. --vjsd-page-background-opacity: 0.4;
  330. }
  331. .vjsd-dialog-backdrop,
  332. .vjsd-dialog {
  333. --vjsd-page-background-filter: void;
  334. --vjsd-page-background-opacity: void;
  335. }
  336. body > * {
  337. filter: var(--vjsd-page-background-filter);
  338. opacity: calc(var(--vjsd-page-background-opacity) * 1.0);
  339. }
  340. `;
  341. /**
  342. *
  343. * @typedef { (...args: HTMLElement[]) => void } onElementGenerated
  344. *
  345. * */
  346. /*
  347. class Derived extends Base {
  348. constructor() {
  349. super();
  350. this.field = 1;
  351. console.log("Derived constructor:", this.field);
  352. this.field = 2;
  353. }
  354. }
  355. */
  356. // let __ceId__ =0;
  357. // const __ceIdStore__ = new WeakMap();
  358. // This is just for common utils.
  359. class VanillaJSDialogMethods {
  360. constructor() {
  361. /**
  362. * @type {object} __widgets__ - store of widgets (private)
  363. */
  364. this.__widgets__ = {};
  365. this.esProxyHandler = {
  366. get(obj, prop) {
  367. const elm = obj[prop];
  368. if (elm instanceof HTMLElement) {
  369. return elm;
  370. }
  371. console.warn(`Element '${prop}' is not yet assigned.`);
  372. return null;
  373. }
  374. };
  375. }
  376. /**
  377. * @returns { Object.<string, (...args?: ( onElementGenerated|string|number)[])=>HTMLElement > }
  378. */
  379. get widgets() {
  380. return this.__widgets__
  381. };
  382. set widgets(newWidgets) {
  383. if ('prototype' in newWidgets) {
  384. // class
  385. newWidgets = new newWidgets;
  386. }
  387. // object
  388. Object.assign(this.__widgets__, newWidgets);
  389. return true;
  390. }
  391. /**
  392. *
  393. * @param {HTMLElement} elm
  394. * @param {string} parentSelector
  395. * @param {string} childSelector
  396. * @returns
  397. */
  398. query(elm, parentSelector, childSelector) {
  399. return elm.closest(parentSelector).querySelector(childSelector)
  400. }
  401. /**
  402. *
  403. * @param {HTMLElement} elm
  404. * @param {string} parentSelector
  405. * @param {string} childSelector
  406. * @returns
  407. */
  408. querys(elm, parentSelector, childSelector) {
  409. return elm.closest(parentSelector).querySelectorAll(childSelector)
  410. }
  411. /**
  412. * You might override it using userscript manager's css loader.
  413. * @param {...string} urls external url of the css file
  414. */
  415. importCSS(...urls) {
  416. /*
  417. // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js#sha512=qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==
  418. < script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer" >< /script >
  419. */
  420. const elements = urls.map(url => {
  421. let elm = document.createElement('link');
  422. elm.setAttribute('rel', 'stylesheet');
  423. elm.setAttribute('href', url);
  424. if (url.includes('#')) {
  425. let idx1 = url.indexOf('#');
  426. let idx2 = url.indexOf('=', idx1);
  427. if (idx1 > 1 && idx2 === idx1 + 7) {
  428. let s = url.substring(idx1 + 1, idx2);
  429. switch (s) {
  430. case 'sha256':
  431. case 'sha384':
  432. case 'sha512':
  433. elm.setAttribute('integrity', `${s}-${url.substring(idx2 + 1)}`);
  434. }
  435. }
  436. }
  437. elm.setAttribute('crossorigin', 'anonymous');
  438. elm.setAttribute('referrerpolicy', 'no-referrer');
  439. // document.head.appendChild(elm);
  440. return elm;
  441. })
  442. document.head.append(...elements);
  443. return urls.length === 1 ? elements[0] : elements;
  444. }
  445. // ceToString(){
  446. // return `${__ceIdStore__.toString.call(this)} #${__ceIdStore__.get(this)}`;
  447. // }
  448. /**
  449. *
  450. * @param {string} tag
  451. * @param {Object.<string, any?>} props
  452. * @param {Object.<string, string?>} attrs
  453. * @returns {HTMLElement}
  454. */
  455. ce(tag, props, attrs) {
  456. /** @type {HTMLElement} */
  457. const elm = (tag instanceof HTMLElement) ? elm :
  458. (typeof tag == 'string') ? document.createElement(tag) :
  459. console.assert(false, "argument invalid");
  460. if (props) Object.assign(elm, props);
  461. if (attrs) {
  462. for (const k of Object.keys(attrs)) {
  463. elm.setAttribute(k, attrs[k]);
  464. }
  465. }
  466. // __ceIdStore__.set(elm, ++__ceId__);
  467. // elm.toString = this.ceToString;
  468. return elm;
  469. }
  470. /**
  471. *
  472. * @param {string} t
  473. * @param {string} [id]
  474. * @returns
  475. */
  476. addCSS(t, id) {
  477. let styleElm = document.createElement('style');
  478. styleElm.textContent = t;
  479. if (id) styleElm.id = id;
  480. document.head.appendChild(styleElm);
  481. return styleElm;
  482. }
  483. randomInputId() {
  484. const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  485. const r###ltArr = new Array(8);
  486. for (let i = 0; i < 8; i++) {
  487. r###ltArr[i] = chars.charAt(Math.floor(Math.random() * (i ? 36 : 26)));
  488. }
  489. return r###ltArr.join('');
  490. }
  491. /**
  492. *
  493. * @param {HTMLElement} elm
  494. * @param {Object.<string, string|number> | Function | any[]} args
  495. * @returns
  496. * */
  497. st(elm, ...args) {
  498. console.assert(elm instanceof HTMLElement, 'HTMLElement shall be required.');
  499. if (args.length === 0) return;
  500. if ('length' in args[0]) args = args[0];
  501. let f = null;
  502. for (const arg of args) {
  503. if (typeof arg == 'function') {
  504. f = arg;
  505. } else if (typeof arg == 'object') {
  506. const obj = arg;
  507. for (const k of Object.keys(obj)) {
  508. if (k in elm) {
  509. if (k === 'className' && elm[k].length > 0) obj[k] = `${elm[k]} ${obj[k]}`;
  510. elm[k] = obj[k];
  511. } else elm.setAttribute(k, obj[k]);
  512. }
  513. }
  514. }
  515. if (f instanceof Function) f(elm);
  516. }
  517. }
  518. const S = new VanillaJSDialogMethods();
  519. class VanillaJSDialog {
  520. // CAUTION: DO NOT CACHE ELEMENTS IN THE NESTED FUNCTIONS.
  521. constructor() {
  522. this.S = S;
  523. this.shown = false;
  524. /**
  525. * @type {Function | null} backdropClickHandler - the function handler for backdrop click
  526. */
  527. this.backdropClickHandler = null;
  528. this.backdrop = '';
  529. /** @type {Map<string, Function>} */
  530. this.clicks2 = new Map(); /* the string key is just an arbitrary id for the click handler */
  531. /** @type {Function?} */
  532. this.clickHandler = null;
  533. /** @type {VanillaJSDialog} */
  534. this._es_proxy_ = new Proxy({}, S.esProxyHandler);
  535. if (!S.firstDialogCreated) this.onFirstCreation();
  536. this.init();
  537. console.assert(this.es.dialog instanceof HTMLElement, 'es.dialog must be set.');
  538. if (this.clickHandler !== null) {
  539. this.es.dialog.addEventListener('click', this.clickHandler, true);
  540. }
  541. S.firstDialogCreated = true;
  542. }
  543. /** @returns {Object.<string, HTMLElement?>} */
  544. get es() {
  545. return this._es_proxy_;
  546. }
  547. onFirstCreation() {
  548. // TODO
  549. }
  550. init() {
  551. // TODO
  552. }
  553. get themeProps() {
  554. return _themeProps_;
  555. }
  556. get cssForThemeProps() {
  557. return _cssForThemeProps_;
  558. }
  559. themeSetup() {
  560. S.addCSS(this.cssForThemeProps(this.themeProps), 'vjsd-style');
  561. }
  562. onBeforeShow() {
  563. // TODO
  564. }
  565. onShow() {
  566. // TODO
  567. }
  568. show() {
  569. if (this.shown === true) return;
  570. if (this.onBeforeShow() === false) return;
  571. let { dialog } = this.es;
  572. dialog.classList.add('vjsd-dialog-visible');
  573. this.shown = true;
  574. if (this.backdrop === 'dismiss' || this.backdrop === 'block') {
  575. if (this.backdropClickHandler === null) {
  576. this.backdropClickHandler = () => {
  577. const shown = this.shown;
  578. if (shown && this.backdrop === 'dismiss') {
  579. this.dismiss();
  580. }
  581. };
  582. }
  583. if (!('backdrop' in this.es)) {
  584. const backdrop = S.ce('div', {
  585. className: 'vjsd-dialog-backdrop'
  586. });
  587. backdrop.setAttribute('__vjsd__', '');
  588. backdrop.addEventListener('click', this.backdropClickHandler, true);
  589. document.body.appendChild(backdrop);
  590. this.es.backdrop = backdrop;
  591. }
  592. document.documentElement.classList.add('vjsd-dialog-shown');
  593. this.es.backdrop.classList.add('vjsd-backdrop-visible');
  594. }
  595. dialog.classList.toggle('vjsd-dark', this.isDarkTheme());
  596. this.onShow();
  597. }
  598. onBeforeDismiss() {
  599. // TODO
  600. }
  601. onDismiss() {
  602. // TODO
  603. }
  604. dismiss() {
  605. if (this.shown) {
  606. if (this.onBeforeDismiss() === false) return;
  607. document.documentElement.classList.remove('vjsd-dialog-shown');
  608. const es = this.es;
  609. es.dialog.classList.remove('vjsd-dialog-visible');
  610. if ('backdrop' in es) {
  611. let backdrop = es.backdrop;
  612. if (backdrop instanceof HTMLElement && backdrop.classList.contains('vjsd-backdrop-visible')) {
  613. backdrop.classList.remove('vjsd-backdrop-visible');
  614. }
  615. }
  616. this.shown = false;
  617. this.onDismiss();
  618. }
  619. }
  620. isDarkTheme() {
  621. // TODO - shall be overrided
  622. return false;
  623. }
  624. createClickHandler() {
  625. const clicks2 = this.clicks2;
  626. return (evt) => {
  627. let evtTarget = ((evt || 0).target || 0);
  628. if (!(evtTarget instanceof HTMLElement)) return;
  629. let vjsdElement = evtTarget.closest('[vjsd-clickable]');
  630. if (vjsdElement instanceof HTMLElement) {
  631. let p = vjsdElement.getAttribute('vjsd-clickable');
  632. let f = clicks2.get(p);
  633. if (f instanceof Function) f(evt);
  634. }
  635. };
  636. }
  637. /**
  638. *
  639. * @param {HTMLElement | string} elm
  640. * @param {Function} func
  641. *
  642. * */
  643. clickable(elm, func) {
  644. if (typeof elm == 'string') {
  645. this.clicks2.set(elm, func);
  646. }
  647. if (this.clickHandler === null) this.clickHandler = this.createClickHandler();
  648. }
  649. };
  650. VanillaJSDialog.S = S;
  651. VanillaJSDialog.setup1 = function () {
  652. const S = this.S;
  653. S.widgets = {
  654. /**
  655. * [@Override] The user shall set a customized method to replace VJSD.icon for customization
  656. * @param {string} iconTag Icon Tag
  657. * @returns {VE} generated VE
  658. */
  659. icon(iconTag) {
  660. return S.ce('i', { className: 'vjsd-icon vjsd-icon-' + iconTag });
  661. // return VJSD.iconBuilder(VJSD.ce('span', {className:'vjsd-icon'}), iconTag);
  662. },
  663. title(text, ...args) {
  664. const elm = S.ce('span', { className: 'vjsd-title', textContent: text });
  665. S.st(elm, args);
  666. return elm;
  667. },
  668. buttonIcon(iconTag, ...args) {
  669. const icon = S.widgets.icon(iconTag);
  670. icon.classList.add('vjsd-buttonicon');
  671. S.st(icon, args)
  672. return icon;
  673. },
  674. labeledCheckbox(className, text, f) {
  675. let elmLabel = S.ce('label', {
  676. className: 'vjsd-checkbox-label'
  677. });
  678. let elmInput = S.ce('input', {
  679. className
  680. }, {
  681. 'type': 'checkbox'
  682. })
  683. elmLabel.append(elmInput, text + "")
  684. if (f instanceof Function) f(elmLabel, elmInput);
  685. return elmLabel;
  686. },
  687. labeledRadio(className, text, f) {
  688. let elmLabel = S.ce('label', {
  689. className: 'vjsd-checkbox-label'
  690. });
  691. let elmInput = S.ce('input', {
  692. className
  693. }, {
  694. 'type': 'radio'
  695. });
  696. elmLabel.append(elmInput, text + "");
  697. if (f instanceof Function) f(elmLabel, elmInput);
  698. return elmLabel;
  699. },
  700. button(text, ...args) {
  701. let elm = S.ce('div', { className: 'vjsd-button', textContent: text });
  702. S.st(elm, args)
  703. return elm;
  704. },
  705. space() {
  706. return S.ce('div', { className: 'vjsd-space' });
  707. },
  708. span(text) {
  709. return S.ce('span', { className: 'vjsd-span', textContent: text });
  710. },
  711. inputText(f) {
  712. let elm = S.ce('input', { className: 'vjsd-input' }, {
  713. 'type': 'text',
  714. id: S.randomInputId(),
  715. autocomplete: "off"
  716. });
  717. if (f instanceof Function) f(elm);
  718. return elm
  719. }
  720. };
  721. }
  722. VanillaJSDialog.VanillaJSDialogMethods = VanillaJSDialogMethods;
  723. // Export to external environment
  724. try { window.VanillaJSDialog = VanillaJSDialog; } catch (error) { /* for Greasemonkey */ }
  725. try { module.VanillaJSDialog = VanillaJSDialog; } catch (error) { /* for CommonJS */ }
  726. // module.exports = VanillaJSDialog
  727. return VanillaJSDialog;
  728. })();