Vanilla JS Dialog

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

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