components

Components library for AniList Edit Multiple Media Simultaneously

目前为 2024-06-02 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/496874/1387736/components.js

  1. // ==UserScript==
  2. // @name components
  3. // @license MIT
  4. // @namespace rtonne
  5. // @match https://anilist.co/*
  6. // @version 1.0
  7. // @author Rtonne
  8. // @description Components library for AniList Edit Multiple Media Simultaneously
  9. // ==/UserScript==
  10.  
  11. /**
  12. * Creates a select input.
  13. * @param {HTMLElement} container A parent element to append the input to.
  14. * @param {string[]} options The option values for the select input.
  15. * @returns The select input element.
  16. */
  17. function createSelectInput(container, options) {
  18. const input_container_1 = document.createElement("div");
  19. input_container_1.className = "el-select";
  20. input_container_1.style.width = "100%";
  21. container.append(input_container_1);
  22. const input_container_2 = document.createElement("div");
  23. input_container_2.className = "el-input el-input--suffix";
  24. input_container_1.append(input_container_2);
  25. const input = document.createElement("input");
  26. input.className = "el-input__inner";
  27. input.readOnly = true;
  28. input.autocomplete = "off";
  29. input_container_2.append(input);
  30. const input_suffix = document.createElement("span");
  31. input_suffix.className = "el-input__suffix";
  32. input_container_2.append(input_suffix);
  33. const input_suffix_inner = document.createElement("span");
  34. input_suffix_inner.className = "el-input__suffix-inner";
  35. input_suffix.append(input_suffix_inner);
  36. const input_icon = document.createElement("i");
  37. input_icon.className = "el-select__caret el-input__icon el-icon-arrow-up";
  38. input_suffix_inner.append(input_icon);
  39.  
  40. input.value = options[0];
  41.  
  42. const dropdown = document.createElement("div");
  43. dropdown.className = "el-select-dropdown el-popper";
  44. dropdown.style.minWidth = "180px";
  45. dropdown.style.zIndex = "10000";
  46. dropdown.style.position = "absolute";
  47. dropdown.style.transition =
  48. "transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1)";
  49. dropdown.style.opacity = "0";
  50. container.append(dropdown);
  51. const dropdown_arrow = document.createElement("div");
  52. dropdown_arrow.className = "popper__arrow";
  53. dropdown_arrow.style.left = "35px";
  54. dropdown_arrow.setAttribute("x-arrow", "");
  55. dropdown.append(dropdown_arrow);
  56. const dropdown_scrollbar = document.createElement("div");
  57. dropdown_scrollbar.className = "el-scrollbar";
  58. dropdown.append(dropdown_scrollbar);
  59. const dropdown_list_container = document.createElement("div");
  60. dropdown_list_container.className =
  61. "el-select-dropdown__wrap el-scrollbar__wrap";
  62. dropdown_list_container.style.overflow = "auto";
  63. dropdown_scrollbar.append(dropdown_list_container);
  64. const dropdown_list = document.createElement("ul");
  65. dropdown_list.className = "el-scrollbar__view el-select-dropdown__list";
  66. dropdown_list_container.append(dropdown_list);
  67. for (const option of options) {
  68. const dropdown_list_item = document.createElement("li");
  69. dropdown_list_item.className = "el-select-dropdown__item";
  70. dropdown_list_item.innerText = option;
  71. dropdown_list_item.onmousedown = () => {
  72. input.value = option;
  73. };
  74. dropdown_list.append(dropdown_list_item);
  75. }
  76. const dropdown_dims = dropdown.getBoundingClientRect();
  77. const dropdown_arrow_dims = dropdown_arrow.getBoundingClientRect();
  78. const full_dropdown_height =
  79. dropdown_dims.height + dropdown_arrow_dims.height;
  80. dropdown.style.transform = "scaleY(0)";
  81.  
  82. function setDropdownPosition() {
  83. const input_dims = input_container_1.getBoundingClientRect();
  84. const dropdown_fits_below =
  85. window.innerHeight - input_dims.bottom >= full_dropdown_height;
  86. if (dropdown_fits_below) {
  87. dropdown.style.top = `${window.scrollY + input_dims.bottom}px`;
  88. dropdown.setAttribute("x-placement", "bottom-start");
  89. dropdown.style.transformOrigin = "center top";
  90. } else {
  91. // Subtract 17px for the margins
  92. dropdown.style.top = `${
  93. window.scrollY + input_dims.top - dropdown_dims.height - 17
  94. }px`;
  95. dropdown.setAttribute("x-placement", "top-start");
  96. dropdown.style.transformOrigin = "center bottom";
  97. }
  98. dropdown.style.left = `${window.scrollX + input_dims.left}px`;
  99. }
  100.  
  101. new IntersectionObserver(
  102. () => {
  103. setDropdownPosition();
  104. },
  105. {
  106. rootMargin: `0px 0px -${dropdown_dims.height}px 0px`,
  107. threshold: 1,
  108. }
  109. ).observe(input_container_1);
  110.  
  111. let isFocused = false;
  112. input_container_1.onclick = (event) => {
  113. if (isFocused) {
  114. input.blur();
  115. } else {
  116. input.focus();
  117. }
  118. };
  119. input.onmousedown = () => false; // Prevent default
  120.  
  121. input.onfocus = () => {
  122. isFocused = true;
  123. setDropdownPosition();
  124. input_container_2.className += " is-focus";
  125. input_icon.className += " is-reverse";
  126.  
  127. for (const item of dropdown_list.children) {
  128. item.classList.remove("selected");
  129. if (item.innerText === input.value) {
  130. item.className += " selected";
  131. }
  132. }
  133.  
  134. dropdown.style.transform = "scaleY(1)";
  135. dropdown.style.opacity = "1";
  136. };
  137.  
  138. input.onblur = () => {
  139. isFocused = false;
  140. input_container_2.classList.remove("is-focus");
  141. input_icon.classList.remove("is-reverse");
  142. dropdown.style.transform = "scaleY(0)";
  143. dropdown.style.opacity = "0";
  144. };
  145.  
  146. // To prevent the input blurring when clicking the icon
  147. input_icon.onmousedown = (event) => {
  148. event.preventDefault();
  149. };
  150.  
  151. return input;
  152. }
  153.  
  154. /**
  155. * Creates a number input. Step can be 0 to have step=1 and to not limit values to steppable ones.
  156. * @returns The number input element.
  157. * @param {HTMLElement} container A parent element to append the input to.
  158. * @param {number} max_value The maximum value the input can reach.
  159. * @param {number} step The step value of the input.
  160. */
  161. function createNumberInput(container, max_value = Infinity, step = 1) {
  162. const input_container_1 = document.createElement("div");
  163. input_container_1.className = "el-input-number is-controls-right";
  164. input_container_1.style.width = "100%";
  165. container.append(input_container_1);
  166. const input_decrease_button = document.createElement("span");
  167. input_decrease_button.className = "el-input-number__decrease is-disabled";
  168. input_decrease_button.role = "button";
  169. input_container_1.append(input_decrease_button);
  170. const input_decrease_button_arrow = document.createElement("i");
  171. input_decrease_button_arrow.className = "el-icon-arrow-down";
  172. input_decrease_button.append(input_decrease_button_arrow);
  173. const input_increase_button = document.createElement("span");
  174. input_increase_button.className = "el-input-number__increase";
  175. input_increase_button.role = "button";
  176. input_container_1.append(input_increase_button);
  177. const input_increase_button_arrow = document.createElement("i");
  178. input_increase_button_arrow.className = "el-icon-arrow-up";
  179. input_increase_button.append(input_increase_button_arrow);
  180. const input_container_2 = document.createElement("div");
  181. input_container_2.className = "el-input";
  182. input_container_1.append(input_container_2);
  183. const input = document.createElement("input");
  184. input.className = "el-input__inner";
  185. input.type = "number";
  186. input.min = input.value = 0;
  187. input.max = max_value;
  188. input.step = step;
  189. input_container_2.append(input);
  190.  
  191. function setButtonDisabledStatus() {
  192. if (Number(input.value) <= input_min) {
  193. input_decrease_button.className += " is-disabled";
  194. } else {
  195. input_decrease_button.classList.remove("is-disabled");
  196. }
  197. if (Number(input.value) >= input_max) {
  198. input_increase_button.className += " is-disabled";
  199. } else {
  200. input_increase_button.classList.remove("is-disabled");
  201. }
  202. }
  203. input_decrease_button.onclick = () => {
  204. input.stepDown();
  205. setButtonDisabledStatus();
  206. };
  207. input_increase_button.onclick = () => {
  208. input.stepUp();
  209. setButtonDisabledStatus();
  210. };
  211. input.oninput = setButtonDisabledStatus;
  212.  
  213. const input_max = Number(input.max);
  214. const input_min = Number(input.min);
  215. function makeValueValid() {
  216. // https://stackoverflow.com/questions/17369098/simplest-way-of-getting-the-number-of-decimals-in-a-number-in-javascript
  217. // Step 0 is a special case that should ignore step validation
  218. if (step !== 0 && Math.floor(Number(input.value)) !== Number(input.value)) {
  219. let decimalCount;
  220. if (input.value.indexOf(".") !== -1 && input.value.indexOf("-") !== -1) {
  221. decimalCount =
  222. input.value.split(/[.-]/)[1].length + input.value.split("-")[1] || 0;
  223. } else if (input.value.indexOf(".") !== -1) {
  224. decimalCount = input.value.split(".")[1].length || 0;
  225. } else {
  226. decimalCount = input.value.split("-")[1] || 0;
  227. }
  228. // Using Math.round to clean up arithmetic imprecisions
  229. const remainder =
  230. Math.round((Number(input.value) % step) * Math.pow(10, decimalCount)) /
  231. Math.pow(10, decimalCount);
  232. input.value = Number(input.value) - remainder;
  233. }
  234. if (Number(input.value) > input_max) {
  235. input.value = input_max;
  236. }
  237. if (Number(input.value) < input_min) {
  238. input.value = input_min;
  239. }
  240. }
  241. input.onblur = makeValueValid;
  242. input.onkeydown = (event) => {
  243. if (event.key === "Enter") {
  244. makeValueValid();
  245. }
  246. };
  247.  
  248. return input;
  249. }
  250.  
  251. /**
  252. * Creates a date input.
  253. * @param {HTMLElement} container A parent element to append the input to.
  254. * @returns The date input element.
  255. */
  256. function createDateInput(container) {
  257. const input_container = document.createElement("div");
  258. input_container.className = "el-input el-input--suffix";
  259. container.append(input_container);
  260. const input = document.createElement("input");
  261. input.className = "el-input__inner";
  262. input.type = "date";
  263. input.style.width = "100%";
  264. input_container.append(input);
  265. const input_icon_container = document.createElement("span");
  266. input_icon_container.className = "el-input__suffix";
  267. input_container.append(input_icon_container);
  268. const input_icon = document.createElement("i");
  269. input_icon.className = "el-input__icon el-icon-date";
  270. input_icon.style.pointerEvents = "auto";
  271. input_icon_container.append(input_icon);
  272.  
  273. input_icon.onclick = () => {
  274. input.showPicker();
  275. };
  276.  
  277. return input;
  278. }
  279.  
  280. /**
  281. * Creates a textarea.
  282. * @param {HTMLElement} container A parent element to append the input to.
  283. * @returns The textarea element.
  284. */
  285. function createTextarea(container) {
  286. const textarea_container = document.createElement("div");
  287. textarea_container.className = "el-textarea";
  288. container.append(textarea_container);
  289. const textarea = document.createElement("textarea");
  290. textarea.className = "el-textarea__inner";
  291. textarea.style.minHeight = "34px";
  292. textarea_container.append(textarea);
  293.  
  294. return textarea;
  295. }
  296.  
  297. /**
  298. * Creates a checkbox.
  299. * @param {HTMLElement} container A parent element to append the checkbox to.
  300. * @param {string} text The text of the checkbox's label.
  301. * @returns The checkbox element.
  302. */
  303. function createCheckbox(container, text) {
  304. const checkbox_container = document.createElement("div");
  305. checkbox_container.className = "rtonne-anilist-multiselect-checkbox";
  306. checkbox_container.style.paddingBottom = "4px";
  307. container.append(checkbox_container);
  308. const label = document.createElement("label");
  309. label.innerText = text;
  310. label.className = "el-checkbox";
  311. label.style.fontSize = "1.2rem";
  312. label.style.fontWeight = "400";
  313. checkbox_container.append(label);
  314. const middle_label = document.createElement("label");
  315. middle_label.className = "el-checkbox__input";
  316. middle_label.style.marginRight = "4px";
  317. middle_label.style.verticalAlign = "text-top";
  318. label.prepend(middle_label);
  319. const button_label = document.createElement("label");
  320. button_label.className = "el-checkbox__inner";
  321. button_label.style.cursor = "pointer";
  322. middle_label.append(button_label);
  323. const checkbox = document.createElement("input");
  324. checkbox.type = "checkbox";
  325. checkbox.className = "el-checkbox__original";
  326. button_label.prepend(checkbox);
  327.  
  328. checkbox.onchange = () => {
  329. if (checkbox.checked) {
  330. label.className += " is-checked";
  331. middle_label.className += " is-checked";
  332. } else {
  333. label.classList.remove("is-checked");
  334. middle_label.classList.remove("is-checked");
  335. }
  336. };
  337.  
  338. return checkbox;
  339. }
  340.  
  341. /**
  342. * Creates an indeterminate checkbox.
  343. * When the return checkbox.readOnly or checkbox.indeterminate is true,
  344. * it is on a 3rd state where it isn't on nor off.
  345. * From https://css-tricks.com/indeterminate-checkboxes/.
  346. * @param {HTMLElement} container A parent element to append the input to.
  347. * @param {string} text The text of the checkbox's label.
  348. * @returns The checkbox element.
  349. */
  350. function createIndeterminateCheckbox(container, text) {
  351. const checkbox_container = document.createElement("div");
  352. checkbox_container.className = "rtonne-anilist-multiselect-checkbox";
  353. checkbox_container.style.paddingBottom = "4px";
  354. container.append(checkbox_container);
  355. const label = document.createElement("label");
  356. label.innerText = text;
  357. label.className = "el-checkbox";
  358. label.style.fontSize = "1.2rem";
  359. label.style.fontWeight = "400";
  360. checkbox_container.append(label);
  361. const middle_label = document.createElement("label");
  362. middle_label.className = "el-checkbox__input";
  363. middle_label.style.marginRight = "4px";
  364. middle_label.style.verticalAlign = "text-top";
  365. label.prepend(middle_label);
  366. const button_label = document.createElement("label");
  367. button_label.className = "el-checkbox__inner";
  368. button_label.style.cursor = "pointer";
  369. middle_label.append(button_label);
  370. const checkbox = document.createElement("input");
  371. checkbox.type = "checkbox";
  372. checkbox.className = "el-checkbox__original";
  373. checkbox.readOnly = true;
  374. checkbox.indeterminate = true;
  375. button_label.prepend(checkbox);
  376.  
  377. checkbox.onclick = () => {
  378. if (checkbox.readOnly) {
  379. checkbox.checked = checkbox.readOnly = false;
  380. } else if (!checkbox.checked) {
  381. checkbox.readOnly = checkbox.indeterminate = true;
  382. }
  383. };
  384.  
  385. checkbox.onchange = () => {
  386. if (checkbox.checked) {
  387. label.className += " is-checked";
  388. middle_label.className += " is-checked";
  389. } else {
  390. label.classList.remove("is-checked");
  391. middle_label.classList.remove("is-checked");
  392. }
  393. };
  394.  
  395. return checkbox;
  396. }
  397.  
  398. /**
  399. * Creates a button.
  400. * @param {HTMLElement} container A parent element to append the input to.
  401. * @param {string} text The text inside the button.
  402. * @returns The button element.
  403. */
  404. function createButton(container, text) {
  405. const button = document.createElement("button");
  406. button.innerText = text;
  407. button.style.backgroundColor = "rgb(var(--color-blue-600))";
  408. button.style.color = "rgb(var(--color-text-bright))";
  409. button.style.border = "none";
  410. button.style.borderRadius = "3px";
  411. button.style.cursor = "pointer";
  412. button.style.fontSize = "12px";
  413. button.style.padding = "9px 15px";
  414. button.style.transition = ".2s";
  415. container.append(button);
  416. return button;
  417. }
  418.  
  419. /**
  420. * Creates a cancel button.
  421. * @param {HTMLElement} container A parent element to append the input to.
  422. * @param {string} text The text inside the button.
  423. * @returns The button element.
  424. */
  425. function createCancelButton(container, text) {
  426. const button = createButton(container, text);
  427. button.style.backgroundColor = "rgba(var(--color-background),.8)";
  428. button.style.color = "rgb(var(--color-text))";
  429. return button;
  430. }
  431.  
  432. /**
  433. * Creates a cancel button with a lighter background.
  434. * @param {HTMLElement} container A parent element to append the input to.
  435. * @param {string} text The text inside the button.
  436. * @returns The button element.
  437. */
  438. function createCancelLighterButton(container, text) {
  439. const button = createButton(container, text);
  440. button.style.backgroundColor = "rgba(var(--color-foreground),.8)";
  441. button.style.color = "rgb(var(--color-text))";
  442. return button;
  443. }
  444.  
  445. /**
  446. * Creates a danger button.
  447. * @param {HTMLElement} container A parent element to append the input to.
  448. * @param {string} text The text inside the button.
  449. * @returns The button element.
  450. */
  451. function createDangerButton(container, text) {
  452. const button = createButton(container, text);
  453. button.style.backgroundColor = "rgba(var(--color-red),.8)";
  454. button.style.color = "rgb(var(--color-white))";
  455. return button;
  456. }
  457.  
  458. /**
  459. * Creates a confirmation popup.
  460. * @param {string} title_text A text/html title for the popup.
  461. * @param {string} message_text The text/html content of the popup.
  462. * @returns The confirm button of the popup.
  463. */
  464. function createConfirmPopup(title_text, message_text) {
  465. const modal = document.createElement("div");
  466. modal.className = "v-modal";
  467. modal.style.zIndex = "99999";
  468. document.body.append(modal);
  469.  
  470. const wrapper = document.createElement("div");
  471. wrapper.className = "el-message-box__wrapper";
  472. wrapper.style.zIndex = "100000";
  473. document.body.append(wrapper);
  474. const container = document.createElement("div");
  475. container.className = "el-message-box";
  476. wrapper.append(container);
  477.  
  478. const header = document.createElement("div");
  479. header.className = "el-message-box__header";
  480. container.append(header);
  481. const title = document.createElement("div");
  482. title.className = "el-message-box__title";
  483. title.innerHTML = `<span>${title_text}</span>`;
  484. header.append(title);
  485. const close_button = document.createElement("button");
  486. close_button.className = "el-message-box__headerbtn";
  487. header.append(close_button);
  488. const close_button_icon = document.createElement("i");
  489. close_button_icon.className = "el-message-box__close el-icon-close";
  490. close_button.append(close_button_icon);
  491.  
  492. const content = document.createElement("div");
  493. content.className = "el-message-box__content";
  494. container.append(content);
  495. const message = document.createElement("div");
  496. message.className = "el-message-box__message";
  497. message.innerHTML = `<p>${message_text}</p>`;
  498. content.append(message);
  499.  
  500. const buttons = document.createElement("div");
  501. buttons.className = "el-message-box__btns";
  502. container.append(buttons);
  503. const cancel_button = createCancelButton(buttons, "Cancel");
  504. const confirm_button = createButton(buttons, "Confirm");
  505.  
  506. wrapper.addEventListener("click", (e) => {
  507. // e.stopPropagation() doesn't seem to work so this condition is here
  508. if (e.target !== wrapper) {
  509. return;
  510. }
  511. modal.remove();
  512. wrapper.remove();
  513. });
  514. close_button.onclick = cancel_button.onclick = () => {
  515. modal.remove();
  516. wrapper.remove();
  517. };
  518.  
  519. // Used .addEventListener instead of .onclick
  520. // so either can be used outside this function
  521. confirm_button.addEventListener("click", () => {
  522. modal.remove();
  523. wrapper.remove();
  524. });
  525.  
  526. return confirm_button;
  527. }
  528.  
  529. /**
  530. * Creates an updatable cancel popup.
  531. * @param {string} initial_title
  532. * @param {HTMLElement} initial_content
  533. * @returns The two elements that close the popup with the click event, two functions to update the popup, and a function to close the popup.
  534. */
  535. function createUpdatableCancelPopup(initial_title, initial_content) {
  536. const modal = document.createElement("div");
  537. modal.className = "v-modal";
  538. modal.style.zIndex = "99999";
  539. document.body.append(modal);
  540.  
  541. const wrapper = document.createElement("div");
  542. wrapper.className = "el-message-box__wrapper";
  543. wrapper.style.zIndex = "100000";
  544. document.body.append(wrapper);
  545. const container = document.createElement("div");
  546. container.className = "el-message-box";
  547. wrapper.append(container);
  548.  
  549. const header = document.createElement("div");
  550. header.className = "el-message-box__header";
  551. container.append(header);
  552. const title_element = document.createElement("div");
  553. title_element.className = "el-message-box__title";
  554. title_element.innerHTML = `<span>${initial_title}</span>`;
  555. header.append(title_element);
  556.  
  557. const content_element = document.createElement("div");
  558. content_element.className = "el-message-box__content";
  559. container.append(content_element);
  560. const message = document.createElement("div");
  561. message.className = "el-message-box__message";
  562. message.replaceChildren(initial_content);
  563. content_element.append(message);
  564.  
  565. const buttons = document.createElement("div");
  566. buttons.className = "el-message-box__btns";
  567. container.append(buttons);
  568. const cancel_button = createCancelButton(buttons, "Cancel");
  569.  
  570. function closePopup() {
  571. modal.remove();
  572. wrapper.remove();
  573. }
  574.  
  575. // Used .addEventListener instead of .onclick
  576. // so either can be used outside this function
  577. wrapper.addEventListener("click", (e) => {
  578. // e.stopPropagation() doesn't seem to work so this condition is here
  579. if (e.target !== wrapper) {
  580. return;
  581. }
  582. closePopup();
  583. });
  584. cancel_button.addEventListener("click", () => {
  585. closePopup();
  586. });
  587.  
  588. function changeTitle(title) {
  589. title_element.innerHTML = `<span>${title}</span>`;
  590. }
  591.  
  592. function changeContent(content) {
  593. message.replaceChildren(content);
  594. }
  595.  
  596. return {
  597. popup_wrapper: wrapper,
  598. popup_cancel_button: cancel_button,
  599. changePopupTitle: changeTitle,
  600. changePopupContent: changeContent,
  601. closePopup: closePopup,
  602. };
  603. }
  604.  
  605. /**
  606. * Creates entry specific content to add to a popup.
  607. * @param {string} text Text to display to the left of the cover.
  608. * @param {string} cover The cover to add as a background-image style.
  609. * @param {number} current_index The index of the current entry being show.
  610. * @param {number} total The total entries going to be shown.
  611. * @returns
  612. */
  613. function createEntryPopupContent(text, cover, current_index, total) {
  614. const content = document.createElement("div");
  615. content.style.display = "flex";
  616. content.style.flexWrap = "wrap";
  617. content.style.flexDirection = "column";
  618. content.style.gap = "10px";
  619. content.style.justifyContent = "center";
  620. content.style.alignItems = "center";
  621. content.style.textAlign = "center";
  622. const content_text = document.createElement("span");
  623. content_text.innerHTML = text;
  624. content_text.style.flexGrow = "1";
  625. content.append(content_text);
  626. const content_image = document.createElement("div");
  627. content_image.style.backgroundImage = cover;
  628. content_image.style.backgroundPosition = "50%";
  629. content_image.style.backgroundRepeat = "no-repeat";
  630. content_image.style.backgroundSize = "cover";
  631. content_image.style.borderRadius = "3px";
  632. content_image.style.minHeight = "210px";
  633. content_image.style.minWidth = "150px";
  634. content.append(content_image);
  635. const bar = document.createElement("div");
  636. bar.style.width = "100%";
  637. bar.style.height = "24px";
  638. bar.style.display = "flex";
  639. bar.style.justifyContent = "center";
  640. bar.style.alignItems = "center";
  641. bar.style.textAlign = "center";
  642. bar.style.background = `linear-gradient(90deg, rgb(var(--color-blue)) ${Math.floor(
  643. (current_index / total) * 100
  644. )}%, rgb(var(--color-background)) 0)`;
  645. bar.style.borderRadius = "3px";
  646. content.append(bar);
  647. const bar_text = document.createElement("span");
  648. bar_text.innerText = `${current_index} / ${total}`;
  649. bar_text.style.boxShadow = `inset 0 0 0 100vw rgb(var(--color-background)),
  650. 0 0 0 2px rgb(var(--color-background)),
  651. 0 0 3px 3px rgb(var(--color-background))`;
  652. bar_text.style.borderRadius = "1px";
  653. bar.appendChild(bar_text);
  654. return content;
  655. }
  656.  
  657. /**
  658. * Creates an error popup.
  659. * @param {string} text The message/content of the popup.
  660. * @returns {Promise<boolean>} A promise that returns if the user asked to cancel.
  661. */
  662. function createErrorPopup(text) {
  663. const modal = document.createElement("div");
  664. modal.className = "v-modal";
  665. modal.style.zIndex = "99999";
  666. document.body.append(modal);
  667.  
  668. const wrapper = document.createElement("div");
  669. wrapper.className = "el-message-box__wrapper";
  670. wrapper.style.zIndex = "100000";
  671. document.body.append(wrapper);
  672. const container = document.createElement("div");
  673. container.className = "el-message-box";
  674. wrapper.append(container);
  675.  
  676. const header = document.createElement("div");
  677. header.className = "el-message-box__header";
  678. container.append(header);
  679. const title = document.createElement("div");
  680. title.className = "el-message-box__title";
  681. title.innerHTML = `<span>ERROR<span>`;
  682. header.append(title);
  683. const close_button = document.createElement("button");
  684. close_button.className = "el-message-box__headerbtn";
  685. header.append(close_button);
  686. const close_button_icon = document.createElement("i");
  687. close_button_icon.className = "el-message-box__close el-icon-close";
  688. close_button.append(close_button_icon);
  689.  
  690. const content = document.createElement("div");
  691. content.className = "el-message-box__content";
  692. container.append(content);
  693. const message = document.createElement("div");
  694. message.className = "el-message-box__message";
  695. message.innerHTML = `<p>${text}</p>`;
  696. content.append(message);
  697.  
  698. const buttons = document.createElement("div");
  699. buttons.className = "el-message-box__btns";
  700. container.append(buttons);
  701. const cancel_button = createDangerButton(buttons, "Cancel");
  702. const retry_button = createButton(buttons, "Retry");
  703.  
  704. return new Promise((resolve) => {
  705. wrapper.onclick = (e) => {
  706. // e.stopPropagation() doesn't seem to work so this condition is here
  707. if (e.target !== wrapper) {
  708. return;
  709. }
  710. modal.remove();
  711. wrapper.remove();
  712. resolve(true);
  713. };
  714. close_button.onclick = cancel_button.onclick = () => {
  715. modal.remove();
  716. wrapper.remove();
  717. resolve(true);
  718. };
  719.  
  720. retry_button.onclick = () => {
  721. modal.remove();
  722. wrapper.remove();
  723. resolve(false);
  724. };
  725. });
  726. }
  727.  
  728. /**
  729. * Creates a popup.
  730. * @param {string} title_text A text/html title for the popup.
  731. * @param {string} message_text The text/html content of the popup.
  732. * @returns {Promise<void>}
  733. */
  734. function createPopup(title_text, message_text) {
  735. const modal = document.createElement("div");
  736. modal.className = "v-modal";
  737. modal.style.zIndex = "99999";
  738. document.body.append(modal);
  739.  
  740. const wrapper = document.createElement("div");
  741. wrapper.className = "el-message-box__wrapper";
  742. wrapper.style.zIndex = "100000";
  743. document.body.append(wrapper);
  744. const container = document.createElement("div");
  745. container.className = "el-message-box";
  746. wrapper.append(container);
  747.  
  748. const header = document.createElement("div");
  749. header.className = "el-message-box__header";
  750. container.append(header);
  751. const title = document.createElement("div");
  752. title.className = "el-message-box__title";
  753. title.innerHTML = `<span>${title_text}</span>`;
  754. header.append(title);
  755. const close_button = document.createElement("button");
  756. close_button.className = "el-message-box__headerbtn";
  757. header.append(close_button);
  758. const close_button_icon = document.createElement("i");
  759. close_button_icon.className = "el-message-box__close el-icon-close";
  760. close_button.append(close_button_icon);
  761.  
  762. const content = document.createElement("div");
  763. content.className = "el-message-box__content";
  764. container.append(content);
  765. const message = document.createElement("div");
  766. message.className = "el-message-box__message";
  767. message.innerHTML = `<p>${message_text}</p>`;
  768. content.append(message);
  769.  
  770. const buttons = document.createElement("div");
  771. buttons.className = "el-message-box__btns";
  772. container.append(buttons);
  773. const ok_button = createButton(buttons, "Ok");
  774.  
  775. return new Promise((resolve) => {
  776. wrapper.onclick = (e) => {
  777. // e.stopPropagation() doesn't seem to work so this condition is here
  778. if (e.target !== wrapper) {
  779. return;
  780. }
  781. modal.remove();
  782. wrapper.remove();
  783. resolve();
  784. };
  785. close_button.onclick = ok_button.onclick = () => {
  786. modal.remove();
  787. wrapper.remove();
  788. resolve();
  789. };
  790. });
  791. }

QingJ © 2025

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