vendor: 5,286 bytes, lines 1-153
1/*! 2* sweetalert2 v11.26.3 3* Released under the MIT License. 4*/ 5(function (global, factory) { 6 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 7 typeof define === 'function' && define.amd ? define(factory) : 8 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Sweetalert2 = factory()); 9})(this, (function () { 'use strict'; 10 11 function _assertClassBrand(e, t, n) { 12 if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; 13 throw new TypeError("Private element is not present on this object"); 14 } 15 function _checkPrivateRedeclaration(e, t) { 16 if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); 17 } 18 function _classPrivateFieldGet2(s, a) { 19 return s.get(_assertClassBrand(s, a)); 20 } 21 function _classPrivateFieldInitSpec(e, t, a) { 22 _checkPrivateRedeclaration(e, t), t.set(e, a); 23 } 24 function _classPrivateFieldSet2(s, a, r) { 25 return s.set(_assertClassBrand(s, a), r), r; 26 } 27 28 const RESTORE_FOCUS_TIMEOUT = 100; 29 30 /** @type {GlobalState} */ 31 const globalState = {}; 32 const focusPreviousActiveElement = () => { 33 if (globalState.previousActiveElement instanceof HTMLElement) { 34 globalState.previousActiveElement.focus(); 35 globalState.previousActiveElement = null; 36 } else if (document.body) { 37 document.body.focus(); 38 } 39 }; 40 41 /** 42 * Restore previous active (focused) element 43 * 44 * @param {boolean} returnFocus 45 * @returns {Promise<void>} 46 */ 47 const restoreActiveElement = returnFocus => { 48 return new Promise(resolve => { 49 if (!returnFocus) { 50 return resolve(); 51 } 52 const x = window.scrollX; 53 const y = window.scrollY; 54 globalState.restoreFocusTimeout = setTimeout(() => { 55 focusPreviousActiveElement(); 56 resolve(); 57 }, RESTORE_FOCUS_TIMEOUT); // issues/900 58 59 window.scrollTo(x, y); 60 }); 61 }; 62 63 const swalPrefix = 'swal2-'; 64 65 /** 66 * @typedef {Record<SwalClass, string>} SwalClasses 67 */ 68 69 /** 70 * @typedef {'success' | 'warning' | 'info' | 'question' | 'error'} SwalIcon 71 * @typedef {Record<SwalIcon, string>} SwalIcons 72 */ 73 74 /** @type {SwalClass[]} */ 75 const classNames = ['container', 'shown', 'height-auto', 'iosfix', 'popup', 'modal', 'no-backdrop', 'no-transition', 'toast', 'toast-shown', 'show', 'hide', 'close', 'title', 'html-container', 'actions', 'confirm', 'deny', 'cancel', 'footer', 'icon', 'icon-content', 'image', 'input', 'file', 'range', 'select', 'radio', 'checkbox', 'label', 'textarea', 'inputerror', 'input-label', 'validation-message', 'progress-steps', 'active-progress-step', 'progress-step', 'progress-step-line', 'loader', 'loading', 'styled', 'top', 'top-start', 'top-end', 'top-left', 'top-right', 'center', 'center-start', 'center-end', 'center-left', 'center-right', 'bottom', 'bottom-start', 'bottom-end', 'bottom-left', 'bottom-right', 'grow-row', 'grow-column', 'grow-fullscreen', 'rtl', 'timer-progress-bar', 'timer-progress-bar-container', 'scrollbar-measure', 'icon-success', 'icon-warning', 'icon-info', 'icon-question', 'icon-error', 'draggable', 'dragging']; 76 const swalClasses = classNames.reduce((acc, className) => { 77 acc[className] = swalPrefix + className; 78 return acc; 79 }, /** @type {SwalClasses} */{}); 80 81 /** @type {SwalIcon[]} */ 82 const icons = ['success', 'warning', 'info', 'question', 'error']; 83 const iconTypes = icons.reduce((acc, icon) => { 84 acc[icon] = swalPrefix + icon; 85 return acc; 86 }, /** @type {SwalIcons} */{}); 87 88 const consolePrefix = 'SweetAlert2:'; 89 90 /** 91 * Capitalize the first letter of a string 92 * 93 * @param {string} str 94 * @returns {string} 95 */ 96 const capitalizeFirstLetter = str => str.charAt(0).toUpperCase() + str.slice(1); 97 98 /** 99 * Standardize console warnings 100 * 101 * @param {string | string[]} message 102 */ 103 const warn = message => { 104 console.warn(`${consolePrefix} ${typeof message === 'object' ? message.join(' ') : message}`); 105 }; 106 107 /** 108 * Standardize console errors 109 * 110 * @param {string} message 111 */ 112 const error = message => { 113 console.error(`${consolePrefix} ${message}`); 114 }; 115 116 /** 117 * Private global state for `warnOnce` 118 * 119 * @type {string[]} 120 * @private 121 */ 122 const previousWarnOnceMessages = []; 123 124 /** 125 * Show a console warning, but only if it hasn't already been shown 126 * 127 * @param {string} message 128 */ 129 const warnOnce = message => { 130 if (!previousWarnOnceMessages.includes(message)) { 131 previousWarnOnceMessages.push(message); 132 warn(message); 133 } 134 }; 135 136 /** 137 * Show a one-time console warning about deprecated params/methods 138 * 139 * @param {string} deprecatedParam 140 * @param {string?} useInstead 141 */ 142 const warnAboutDeprecation = (deprecatedParam, useInstead = null) => { 143 warnOnce(`"${deprecatedParam}" is deprecated and will be removed in the next major release.${useInstead ? ` Use "${useInstead}" instead.` : ''}`); 144 }; 145 146 /** 147 * If `arg` is a function, call it (with no arguments or context) and return the result. 148 * Otherwise, just pass the value through 149 * 150 * @param {(() => *) | *} arg 151 * @returns {*} 152 */ 153 const callIfFunction = arg => typeof arg === 'function' ? arg() : arg;
154 155 /** 156 * @param {*} arg 157 * @returns {boolean} 158 */ 159 const hasToPromiseFn = arg => arg && typeof arg.toPromise === 'function'; 160 161 /** 162 * @param {*} arg 163 * @returns {Promise<*>} 164 */ 165 const asPromise = arg => hasToPromiseFn(arg) ? arg.toPromise() : Promise.resolve(arg); 166 167 /** 168 * @param {*
vendor: 10,668 bytes, lines 168-546
168} arg 169 * @returns {boolean} 170 */ 171 const isPromise = arg => arg && Promise.resolve(arg) === arg; 172 173 /** 174 * Gets the popup container which contains the backdrop and the popup itself. 175 * 176 * @returns {HTMLElement | null} 177 */ 178 const getContainer = () => document.body.querySelector(`.${swalClasses.container}`); 179 180 /** 181 * @param {string} selectorString 182 * @returns {HTMLElement | null} 183 */ 184 const elementBySelector = selectorString => { 185 const container = getContainer(); 186 return container ? container.querySelector(selectorString) : null; 187 }; 188 189 /** 190 * @param {string} className 191 * @returns {HTMLElement | null} 192 */ 193 const elementByClass = className => { 194 return elementBySelector(`.${className}`); 195 }; 196 197 /** 198 * @returns {HTMLElement | null} 199 */ 200 const getPopup = () => elementByClass(swalClasses.popup); 201 202 /** 203 * @returns {HTMLElement | null} 204 */ 205 const getIcon = () => elementByClass(swalClasses.icon); 206 207 /** 208 * @returns {HTMLElement | null} 209 */ 210 const getIconContent = () => elementByClass(swalClasses['icon-content']); 211 212 /** 213 * @returns {HTMLElement | null} 214 */ 215 const getTitle = () => elementByClass(swalClasses.title); 216 217 /** 218 * @returns {HTMLElement | null} 219 */ 220 const getHtmlContainer = () => elementByClass(swalClasses['html-container']); 221 222 /** 223 * @returns {HTMLElement | null} 224 */ 225 const getImage = () => elementByClass(swalClasses.image); 226 227 /** 228 * @returns {HTMLElement | null} 229 */ 230 const getProgressSteps = () => elementByClass(swalClasses['progress-steps']); 231 232 /** 233 * @returns {HTMLElement | null} 234 */ 235 const getValidationMessage = () => elementByClass(swalClasses['validation-message']); 236 237 /** 238 * @returns {HTMLButtonElement | null} 239 */ 240 const getConfirmButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.confirm}`)); 241 242 /** 243 * @returns {HTMLButtonElement | null} 244 */ 245 const getCancelButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.cancel}`)); 246 247 /** 248 * @returns {HTMLButtonElement | null} 249 */ 250 const getDenyButton = () => (/** @type {HTMLButtonElement} */elementBySelector(`.${swalClasses.actions} .${swalClasses.deny}`)); 251 252 /** 253 * @returns {HTMLElement | null} 254 */ 255 const getInputLabel = () => elementByClass(swalClasses['input-label']); 256 257 /** 258 * @returns {HTMLElement | null} 259 */ 260 const getLoader = () => elementBySelector(`.${swalClasses.loader}`); 261 262 /** 263 * @returns {HTMLElement | null} 264 */ 265 const getActions = () => elementByClass(swalClasses.actions); 266 267 /** 268 * @returns {HTMLElement | null} 269 */ 270 const getFooter = () => elementByClass(swalClasses.footer); 271 272 /** 273 * @returns {HTMLElement | null} 274 */ 275 const getTimerProgressBar = () => elementByClass(swalClasses['timer-progress-bar']); 276 277 /** 278 * @returns {HTMLElement | null} 279 */ 280 const getCloseButton = () => elementByClass(swalClasses.close); 281 282 // https://github.com/jkup/focusable/blob/master/index.js 283 const focusable = ` 284 a[href], 285 area[href], 286 input:not([disabled]), 287 select:not([disabled]), 288 textarea:not([disabled]), 289 button:not([disabled]), 290 iframe, 291 object, 292 embed, 293 [tabindex="0"], 294 [contenteditable], 295 audio[controls], 296 video[controls], 297 summary 298`; 299 /** 300 * @returns {HTMLElement[]} 301 */ 302 const getFocusableElements = () => { 303 const popup = getPopup(); 304 if (!popup) { 305 return []; 306 } 307 /** @type {NodeListOf<HTMLElement>} */ 308 const focusableElementsWithTabindex = popup.querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])'); 309 const focusableElementsWithTabindexSorted = Array.from(focusableElementsWithTabindex) 310 // sort according to tabindex 311 .sort((a, b) => { 312 const tabindexA = parseInt(a.getAttribute('tabindex') || '0'); 313 const tabindexB = parseInt(b.getAttribute('tabindex') || '0'); 314 if (tabindexA > tabindexB) { 315 return 1; 316 } else if (tabindexA < tabindexB) { 317 return -1; 318 } 319 return 0; 320 }); 321 322 /** @type {NodeListOf<HTMLElement>} */ 323 const otherFocusableElements = popup.querySelectorAll(focusable); 324 const otherFocusableElementsFiltered = Array.from(otherFocusableElements).filter(el => el.getAttribute('tabindex') !== '-1'); 325 return [...new Set(focusableElementsWithTabindexSorted.concat(otherFocusableElementsFiltered))].filter(el => isVisible$1(el)); 326 }; 327 328 /** 329 * @returns {boolean} 330 */ 331 const isModal = () => { 332 return hasClass(document.body, swalClasses.shown) && !hasClass(document.body, swalClasses['toast-shown']) && !hasClass(document.body, swalClasses['no-backdrop']); 333 }; 334 335 /** 336 * @returns {boolean} 337 */ 338 const isToast = () => { 339 const popup = getPopup(); 340 if (!popup) { 341 return false; 342 } 343 return hasClass(popup, swalClasses.toast); 344 }; 345 346 /** 347 * @returns {boolean} 348 */ 349 const isLoading = () => { 350 const popup = getPopup(); 351 if (!popup) { 352 return false; 353 } 354 return popup.hasAttribute('data-loading'); 355 }; 356 357 /** 358 * Securely set innerHTML of an element 359 * https://github.com/sweetalert2/sweetalert2/issues/1926 360 * 361 * @param {HTMLElement} elem 362 * @param {string} html 363 */ 364 const setInnerHtml = (elem, html) => { 365 elem.textContent = ''; 366 if (html) { 367 const parser = new DOMParser(); 368 const parsed = parser.parseFromString(html, `text/html`); 369 const head = parsed.querySelector('head'); 370 if (head) { 371 Array.from(head.childNodes).forEach(child => { 372 elem.appendChild(child); 373 }); 374 } 375 const body = parsed.querySelector('body'); 376 if (body) { 377 Array.from(body.childNodes).forEach(child => { 378 if (child instanceof HTMLVideoElement || child instanceof HTMLAudioElement) { 379 elem.appendChild(child.cloneNode(true)); // https://github.com/sweetalert2/sweetalert2/issues/2507 380 } else { 381 elem.appendChild(child); 382 } 383 }); 384 } 385 } 386 }; 387 388 /** 389 * @param {HTMLElement} elem 390 * @param {string} className 391 * @returns {boolean} 392 */ 393 const hasClass = (elem, className) => { 394 if (!className) { 395 return false; 396 } 397 const classList = className.split(/\s+/); 398 for (let i = 0; i < classList.length; i++) { 399 if (!elem.classList.contains(classList[i])) { 400 return false; 401 } 402 } 403 return true; 404 }; 405 406 /** 407 * @param {HTMLElement} elem 408 * @param {SweetAlertOptions} params 409 */ 410 const removeCustomClasses = (elem, params) => { 411 Array.from(elem.classList).forEach(className => { 412 if (!Object.values(swalClasses).includes(className) && !Object.values(iconTypes).includes(className) && !Object.values(params.showClass || {}).includes(className)) { 413 elem.classList.remove(className); 414 } 415 }); 416 }; 417 418 /** 419 * @param {HTMLElement} elem 420 * @param {SweetAlertOptions} params 421 * @param {string} className 422 */ 423 const applyCustomClass = (elem, params, className) => { 424 removeCustomClasses(elem, params); 425 if (!params.customClass) { 426 return; 427 } 428 const customClass = params.customClass[(/** @type {keyof SweetAlertCustomClass} */className)]; 429 if (!customClass) { 430 return; 431 } 432 if (typeof customClass !== 'string' && !customClass.forEach) { 433 warn(`Invalid type of customClass.${className}! Expected string or iterable object, got "${typeof customClass}"`); 434 return; 435 } 436 addClass(elem, customClass); 437 }; 438 439 /** 440 * @param {HTMLElement} popup 441 * @param {import('./renderers/renderInput').InputClass | SweetAlertInput} inputClass 442 * @returns {HTMLInputElement | null} 443 */ 444 const getInput$1 = (popup, inputClass) => { 445 if (!inputClass) { 446 return null; 447 } 448 switch (inputClass) { 449 case 'select': 450 case 'textarea': 451 case 'file': 452 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses[inputClass]}`); 453 case 'checkbox': 454 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.checkbox} input`); 455 case 'radio': 456 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:checked`) || popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:first-child`); 457 case 'range': 458 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.range} input`); 459 default: 460 return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.input}`); 461 } 462 }; 463 464 /** 465 * @param {HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement} input 466 */ 467 const focusInput = input => { 468 input.focus(); 469 470 // place cursor at end of text in text input 471 if (input.type !== 'file') { 472 // http://stackoverflow.com/a/2345915 473 const val = input.value; 474 input.value = ''; 475 input.value = val; 476 } 477 }; 478 479 /** 480 * @param {HTMLElement | HTMLElement[] | null} target 481 * @param {string | string[] | readonly string[] | undefined} classList 482 * @param {boolean} condition 483 */ 484 const toggleClass = (target, classList, condition) => { 485 if (!target || !classList) { 486 return; 487 } 488 if (typeof classList === 'string') { 489 classList = classList.split(/\s+/).filter(Boolean); 490 } 491 classList.forEach(className => { 492 if (Array.isArray(target)) { 493 target.forEach(elem => { 494 if (condition) { 495 elem.classList.add(className); 496 } else { 497 elem.classList.remove(className); 498 } 499 }); 500 } else { 501 if (condition) { 502 target.classList.add(className); 503 } else { 504 target.classList.remove(className); 505 } 506 } 507 }); 508 }; 509 510 /** 511 * @param {HTMLElement | HTMLElement[] | null} target 512 * @param {string | string[] | readonly string[] | undefined} classList 513 */ 514 const addClass = (target, classList) => { 515 toggleClass(target, classList, true); 516 }; 517 518 /** 519 * @param {HTMLElement | HTMLElement[] | null} target 520 * @param {string | string[] | readonly string[] | undefined} classList 521 */ 522 const removeClass = (target, classList) => { 523 toggleClass(target, classList, false); 524 }; 525 526 /** 527 * Get direct child of an element by class name 528 * 529 * @param {HTMLElement} elem 530 * @param {string} className 531 * @returns {HTMLElement | undefined} 532 */ 533 const getDirectChildByClass = (elem, className) => { 534 const children = Array.from(elem.children); 535 for (let i = 0; i < children.length; i++) { 536 const child = children[i]; 537 if (child instanceof HTMLElement && hasClass(child, className)) { 538 return child; 539 } 540 } 541 }; 542 543 /** 544 * @param {HTMLElement} elem 545 * @param {string} property 546 * @param {
vendor: 2,661 bytes, lines 546-655
546string | number | null | undefined} value 547 */ 548 const applyNumericalStyle = (elem, property, value) => { 549 if (value === `${parseInt(`${value}`)}`) { 550 value = parseInt(value); 551 } 552 if (value || parseInt(`${value}`) === 0) { 553 elem.style.setProperty(property, typeof value === 'number' ? `${value}px` : value); 554 } else { 555 elem.style.removeProperty(property); 556 } 557 }; 558 559 /** 560 * @param {HTMLElement | null} elem 561 * @param {string} display 562 */ 563 const show = (elem, display = 'flex') => { 564 if (!elem) { 565 return; 566 } 567 elem.style.display = display; 568 }; 569 570 /** 571 * @param {HTMLElement | null} elem 572 */ 573 const hide = elem => { 574 if (!elem) { 575 return; 576 } 577 elem.style.display = 'none'; 578 }; 579 580 /** 581 * @param {HTMLElement | null} elem 582 * @param {string} display 583 */ 584 const showWhenInnerHtmlPresent = (elem, display = 'block') => { 585 if (!elem) { 586 return; 587 } 588 new MutationObserver(() => { 589 toggle(elem, elem.innerHTML, display); 590 }).observe(elem, { 591 childList: true, 592 subtree: true 593 }); 594 }; 595 596 /** 597 * @param {HTMLElement} parent 598 * @param {string} selector 599 * @param {string} property 600 * @param {string} value 601 */ 602 const setStyle = (parent, selector, property, value) => { 603 /** @type {HTMLElement | null} */ 604 const el = parent.querySelector(selector); 605 if (el) { 606 el.style.setProperty(property, value); 607 } 608 }; 609 610 /** 611 * @param {HTMLElement} elem 612 * @param {boolean | string | null | undefined} condition 613 * @param {string} display 614 */ 615 const toggle = (elem, condition, display = 'flex') => { 616 if (condition) { 617 show(elem, display); 618 } else { 619 hide(elem); 620 } 621 }; 622 623 /** 624 * borrowed from jquery $(elem).is(':visible') implementation 625 * 626 * @param {HTMLElement | null} elem 627 * @returns {boolean} 628 */ 629 const isVisible$1 = elem => !!(elem && (elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length)); 630 631 /** 632 * @returns {boolean} 633 */ 634 const allButtonsAreHidden = () => !isVisible$1(getConfirmButton()) && !isVisible$1(getDenyButton()) && !isVisible$1(getCancelButton()); 635 636 /** 637 * @param {HTMLElement} elem 638 * @returns {boolean} 639 */ 640 const isScrollable = elem => !!(elem.scrollHeight > elem.clientHeight); 641 642 /** 643 * @param {HTMLElement} element 644 * @param {HTMLElement} stopElement 645 * @returns {boolean} 646 */ 647 const selfOrParentIsScrollable = (element, stopElement) => { 648 let parent = element; 649 while (parent && parent !== stopElement) { 650 if (isScrollable(parent)) { 651 return true; 652 } 653 parent = parent.parentElement; 654 } 655 return false;
vendor: 10,924 bytes, lines 656-991
656 }; 657 658 /** 659 * borrowed from https://stackoverflow.com/a/46352119 660 * 661 * @param {HTMLElement} elem 662 * @returns {boolean} 663 */ 664 const hasCssAnimation = elem => { 665 const style = window.getComputedStyle(elem); 666 const animDuration = parseFloat(style.getPropertyValue('animation-duration') || '0'); 667 const transDuration = parseFloat(style.getPropertyValue('transition-duration') || '0'); 668 return animDuration > 0 || transDuration > 0; 669 }; 670 671 /** 672 * @param {number} timer 673 * @param {boolean} reset 674 */ 675 const animateTimerProgressBar = (timer, reset = false) => { 676 const timerProgressBar = getTimerProgressBar(); 677 if (!timerProgressBar) { 678 return; 679 } 680 if (isVisible$1(timerProgressBar)) { 681 if (reset) { 682 timerProgressBar.style.transition = 'none'; 683 timerProgressBar.style.width = '100%'; 684 } 685 setTimeout(() => { 686 timerProgressBar.style.transition = `width ${timer / 1000}s linear`; 687 timerProgressBar.style.width = '0%'; 688 }, 10); 689 } 690 }; 691 const stopTimerProgressBar = () => { 692 const timerProgressBar = getTimerProgressBar(); 693 if (!timerProgressBar) { 694 return; 695 } 696 const timerProgressBarWidth = parseInt(window.getComputedStyle(timerProgressBar).width); 697 timerProgressBar.style.removeProperty('transition'); 698 timerProgressBar.style.width = '100%'; 699 const timerProgressBarFullWidth = parseInt(window.getComputedStyle(timerProgressBar).width); 700 const timerProgressBarPercent = timerProgressBarWidth / timerProgressBarFullWidth * 100; 701 timerProgressBar.style.width = `${timerProgressBarPercent}%`; 702 }; 703 704 /** 705 * Detect Node env 706 * 707 * @returns {boolean} 708 */ 709 const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined'; 710 711 const sweetHTML = ` 712 <div aria-labelledby="${swalClasses.title}" aria-describedby="${swalClasses['html-container']}" class="${swalClasses.popup}" tabindex="-1"> 713 <button type="button" class="${swalClasses.close}"></button> 714 <ul class="${swalClasses['progress-steps']}"></ul> 715 <div class="${swalClasses.icon}"></div> 716 <img class="${swalClasses.image}" /> 717 <h2 class="${swalClasses.title}" id="${swalClasses.title}"></h2> 718 <div class="${swalClasses['html-container']}" id="${swalClasses['html-container']}"></div> 719 <input class="${swalClasses.input}" id="${swalClasses.input}" /> 720 <input type="file" class="${swalClasses.file}" /> 721 <div class="${swalClasses.range}"> 722 <input type="range" /> 723 <output></output> 724 </div> 725 <select class="${swalClasses.select}" id="${swalClasses.select}"></select> 726 <div class="${swalClasses.radio}"></div> 727 <label class="${swalClasses.checkbox}"> 728 <input type="checkbox" id="${swalClasses.checkbox}" /> 729 <span class="${swalClasses.label}"></span> 730 </label> 731 <textarea class="${swalClasses.textarea}" id="${swalClasses.textarea}"></textarea> 732 <div class="${swalClasses['validation-message']}" id="${swalClasses['validation-message']}"></div> 733 <div class="${swalClasses.actions}"> 734 <div class="${swalClasses.loader}"></div> 735 <button type="button" class="${swalClasses.confirm}"></button> 736 <button type="button" class="${swalClasses.deny}"></button> 737 <button type="button" class="${swalClasses.cancel}"></button> 738 </div> 739 <div class="${swalClasses.footer}"></div> 740 <div class="${swalClasses['timer-progress-bar-container']}"> 741 <div class="${swalClasses['timer-progress-bar']}"></div> 742 </div> 743 </div> 744`.replace(/(^|\n)\s*/g, ''); 745 746 /** 747 * @returns {boolean} 748 */ 749 const resetOldContainer = () => { 750 const oldContainer = getContainer(); 751 if (!oldContainer) { 752 return false; 753 } 754 oldContainer.remove(); 755 removeClass([document.documentElement, document.body], [swalClasses['no-backdrop'], swalClasses['toast-shown'], swalClasses['has-column']]); 756 return true; 757 }; 758 const resetValidationMessage$1 = () => { 759 globalState.currentInstance.resetValidationMessage(); 760 }; 761 const addInputChangeListeners = () => { 762 const popup = getPopup(); 763 const input = getDirectChildByClass(popup, swalClasses.input); 764 const file = getDirectChildByClass(popup, swalClasses.file); 765 /** @type {HTMLInputElement} */ 766 const range = popup.querySelector(`.${swalClasses.range} input`); 767 /** @type {HTMLOutputElement} */ 768 const rangeOutput = popup.querySelector(`.${swalClasses.range} output`); 769 const select = getDirectChildByClass(popup, swalClasses.select); 770 /** @type {HTMLInputElement} */ 771 const checkbox = popup.querySelector(`.${swalClasses.checkbox} input`); 772 const textarea = getDirectChildByClass(popup, swalClasses.textarea); 773 input.oninput = resetValidationMessage$1; 774 file.onchange = resetValidationMessage$1; 775 select.onchange = resetValidationMessage$1; 776 checkbox.onchange = resetValidationMessage$1; 777 textarea.oninput = resetValidationMessage$1; 778 range.oninput = () => { 779 resetValidationMessage$1(); 780 rangeOutput.value = range.value; 781 }; 782 range.onchange = () => { 783 resetValidationMessage$1(); 784 rangeOutput.value = range.value; 785 }; 786 }; 787 788 /** 789 * @param {string | HTMLElement} target 790 * @returns {HTMLElement} 791 */ 792 const getTarget = target => typeof target === 'string' ? document.querySelector(target) : target; 793 794 /** 795 * @param {SweetAlertOptions} params 796 */ 797 const setupAccessibility = params => { 798 const popup = getPopup(); 799 popup.setAttribute('role', params.toast ? 'alert' : 'dialog'); 800 popup.setAttribute('aria-live', params.toast ? 'polite' : 'assertive'); 801 if (!params.toast) { 802 popup.setAttribute('aria-modal', 'true'); 803 } 804 }; 805 806 /** 807 * @param {HTMLElement} targetElement 808 */ 809 const setupRTL = targetElement => { 810 if (window.getComputedStyle(targetElement).direction === 'rtl') { 811 addClass(getContainer(), swalClasses.rtl); 812 } 813 }; 814 815 /** 816 * Add modal + backdrop to DOM 817 * 818 * @param {SweetAlertOptions} params 819 */ 820 const init = params => { 821 // Clean up the old popup container if it exists 822 const oldContainerExisted = resetOldContainer(); 823 if (isNodeEnv()) { 824 error('SweetAlert2 requires document to initialize'); 825 return; 826 } 827 const container = document.createElement('div'); 828 container.className = swalClasses.container; 829 if (oldContainerExisted) { 830 addClass(container, swalClasses['no-transition']); 831 } 832 setInnerHtml(container, sweetHTML); 833 container.dataset['swal2Theme'] = params.theme; 834 const targetElement = getTarget(params.target); 835 targetElement.appendChild(container); 836 if (params.topLayer) { 837 container.setAttribute('popover', ''); 838 container.showPopover(); 839 } 840 setupAccessibility(params); 841 setupRTL(targetElement); 842 addInputChangeListeners(); 843 }; 844 845 /** 846 * @param {HTMLElement | object | string} param 847 * @param {HTMLElement} target 848 */ 849 const parseHtmlToContainer = (param, target) => { 850 // DOM element 851 if (param instanceof HTMLElement) { 852 target.appendChild(param); 853 } 854 855 // Object 856 else if (typeof param === 'object') { 857 handleObject(param, target); 858 } 859 860 // Plain string 861 else if (param) { 862 setInnerHtml(target, param); 863 } 864 }; 865 866 /** 867 * @param {object} param 868 * @param {HTMLElement} target 869 */ 870 const handleObject = (param, target) => { 871 // JQuery element(s) 872 if (param.jquery) { 873 handleJqueryElem(target, param); 874 } 875 876 // For other objects use their string representation 877 else { 878 setInnerHtml(target, param.toString()); 879 } 880 }; 881 882 /** 883 * @param {HTMLElement} target 884 * @param {object} elem 885 */ 886 const handleJqueryElem = (target, elem) => { 887 target.textContent = ''; 888 if (0 in elem) { 889 for (let i = 0; i in elem; i++) { 890 target.appendChild(elem[i].cloneNode(true)); 891 } 892 } else { 893 target.appendChild(elem.cloneNode(true)); 894 } 895 }; 896 897 /** 898 * @param {SweetAlert} instance 899 * @param {SweetAlertOptions} params 900 */ 901 const renderActions = (instance, params) => { 902 const actions = getActions(); 903 const loader = getLoader(); 904 if (!actions || !loader) { 905 return; 906 } 907 908 // Actions (buttons) wrapper 909 if (!params.showConfirmButton && !params.showDenyButton && !params.showCancelButton) { 910 hide(actions); 911 } else { 912 show(actions); 913 } 914 915 // Custom class 916 applyCustomClass(actions, params, 'actions'); 917 918 // Render all the buttons 919 renderButtons(actions, loader, params); 920 921 // Loader 922 setInnerHtml(loader, params.loaderHtml || ''); 923 applyCustomClass(loader, params, 'loader'); 924 }; 925 926 /** 927 * @param {HTMLElement} actions 928 * @param {HTMLElement} loader 929 * @param {SweetAlertOptions} params 930 */ 931 function renderButtons(actions, loader, params) { 932 const confirmButton = getConfirmButton(); 933 const denyButton = getDenyButton(); 934 const cancelButton = getCancelButton(); 935 if (!confirmButton || !denyButton || !cancelButton) { 936 return; 937 } 938 939 // Render buttons 940 renderButton(confirmButton, 'confirm', params); 941 renderButton(denyButton, 'deny', params); 942 renderButton(cancelButton, 'cancel', params); 943 handleButtonsStyling(confirmButton, denyButton, cancelButton, params); 944 if (params.reverseButtons) { 945 if (params.toast) { 946 actions.insertBefore(cancelButton, confirmButton); 947 actions.insertBefore(denyButton, confirmButton); 948 } else { 949 actions.insertBefore(cancelButton, loader); 950 actions.insertBefore(denyButton, loader); 951 actions.insertBefore(confirmButton, loader); 952 } 953 } 954 } 955 956 /** 957 * @param {HTMLElement} confirmButton 958 * @param {HTMLElement} denyButton 959 * @param {HTMLElement} cancelButton 960 * @param {SweetAlertOptions} params 961 */ 962 function handleButtonsStyling(confirmButton, denyButton, cancelButton, params) { 963 if (!params.buttonsStyling) { 964 removeClass([confirmButton, denyButton, cancelButton], swalClasses.styled); 965 return; 966 } 967 addClass([confirmButton, denyButton, cancelButton], swalClasses.styled); 968 969 // Apply custom background colors to action buttons 970 if (params.confirmButtonColor) { 971 confirmButton.style.setProperty('--swal2-confirm-button-background-color', params.confirmButtonColor); 972 } 973 if (params.denyButtonColor) { 974 denyButton.style.setProperty('--swal2-deny-button-background-color', params.denyButtonColor); 975 } 976 if (params.cancelButtonColor) { 977 cancelButton.style.setProperty('--swal2-cancel-button-background-color', params.cancelButtonColor); 978 } 979 980 // Apply the outline color to action buttons 981 applyOutlineColor(confirmButton); 982 applyOutlineColor(denyButton); 983 applyOutlineColor(cancelButton); 984 } 985 986 /** 987 * @param {HTMLElement} button 988 */ 989 function applyOutlineColor(button) { 990 const buttonStyle = window.getComputedStyle(button); 991 if (buttonStyle.getPropertyValue('--swal2-action-button-focus-box-sha
vendor: 4,249 bytes, lines 991-1119
991dow')) { 992 // If the button already has a custom outline color, no need to change it 993 return; 994 } 995 const outlineColor = buttonStyle.backgroundColor.replace(/rgba?\((\d+), (\d+), (\d+).*/, 'rgba($1, $2, $3, 0.5)'); 996 button.style.setProperty('--swal2-action-button-focus-box-shadow', buttonStyle.getPropertyValue('--swal2-outline').replace(/ rgba\(.*/, ` ${outlineColor}`)); 997 } 998 999 /** 1000 * @param {HTMLElement} button 1001 * @param {'confirm' | 'deny' | 'cancel'} buttonType 1002 * @param {SweetAlertOptions} params 1003 */ 1004 function renderButton(button, buttonType, params) { 1005 const buttonName = /** @type {'Confirm' | 'Deny' | 'Cancel'} */capitalizeFirstLetter(buttonType); 1006 toggle(button, params[`show${buttonName}Button`], 'inline-block'); 1007 setInnerHtml(button, params[`${buttonType}ButtonText`] || ''); // Set caption text 1008 button.setAttribute('aria-label', params[`${buttonType}ButtonAriaLabel`] || ''); // ARIA label 1009 1010 // Add buttons custom classes 1011 button.className = swalClasses[buttonType]; 1012 applyCustomClass(button, params, `${buttonType}Button`); 1013 } 1014 1015 /** 1016 * @param {SweetAlert} instance 1017 * @param {SweetAlertOptions} params 1018 */ 1019 const renderCloseButton = (instance, params) => { 1020 const closeButton = getCloseButton(); 1021 if (!closeButton) { 1022 return; 1023 } 1024 setInnerHtml(closeButton, params.closeButtonHtml || ''); 1025 1026 // Custom class 1027 applyCustomClass(closeButton, params, 'closeButton'); 1028 toggle(closeButton, params.showCloseButton); 1029 closeButton.setAttribute('aria-label', params.closeButtonAriaLabel || ''); 1030 }; 1031 1032 /** 1033 * @param {SweetAlert} instance 1034 * @param {SweetAlertOptions} params 1035 */ 1036 const renderContainer = (instance, params) => { 1037 const container = getContainer(); 1038 if (!container) { 1039 return; 1040 } 1041 handleBackdropParam(container, params.backdrop); 1042 handlePositionParam(container, params.position); 1043 handleGrowParam(container, params.grow); 1044 1045 // Custom class 1046 applyCustomClass(container, params, 'container'); 1047 }; 1048 1049 /** 1050 * @param {HTMLElement} container 1051 * @param {SweetAlertOptions['backdrop']} backdrop 1052 */ 1053 function handleBackdropParam(container, backdrop) { 1054 if (typeof backdrop === 'string') { 1055 container.style.background = backdrop; 1056 } else if (!backdrop) { 1057 addClass([document.documentElement, document.body], swalClasses['no-backdrop']); 1058 } 1059 } 1060 1061 /** 1062 * @param {HTMLElement} container 1063 * @param {SweetAlertOptions['position']} position 1064 */ 1065 function handlePositionParam(container, position) { 1066 if (!position) { 1067 return; 1068 } 1069 if (position in swalClasses) { 1070 addClass(container, swalClasses[position]); 1071 } else { 1072 warn('The "position" parameter is not valid, defaulting to "center"'); 1073 addClass(container, swalClasses.center); 1074 } 1075 } 1076 1077 /** 1078 * @param {HTMLElement} container 1079 * @param {SweetAlertOptions['grow']} grow 1080 */ 1081 function handleGrowParam(container, grow) { 1082 if (!grow) { 1083 return; 1084 } 1085 addClass(container, swalClasses[`grow-${grow}`]); 1086 } 1087 1088 /** 1089 * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has. 1090 * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')` 1091 * This is the approach that Babel will probably take to implement private methods/fields 1092 * https://github.com/tc39/proposal-private-methods 1093 * https://github.com/babel/babel/pull/7555 1094 * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module* 1095 * then we can use that language feature. 1096 */ 1097 1098 var privateProps = { 1099 innerParams: new WeakMap(), 1100 domCache: new WeakMap() 1101 }; 1102 1103 /// <reference path="../../../../sweetalert2.d.ts"/> 1104 1105 1106 /** @type {InputClass[]} */ 1107 const inputClasses = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea']; 1108 1109 /** 1110 * @param {SweetAlert} instance 1111 * @param {SweetAlertOptions} params 1112 */ 1113 const renderInput = (instance, params) => { 1114 const popup = getPopup(); 1115 if (!popup) { 1116 return; 1117 } 1118 const innerParams = privateProps.innerParams.get(instance); 1119 const rerender = !innerParams || params.input !== innerParams.input;
vendor: 10,757 bytes, lines 1120-1482
1120 inputClasses.forEach(inputClass => { 1121 const inputContainer = getDirectChildByClass(popup, swalClasses[inputClass]); 1122 if (!inputContainer) { 1123 return; 1124 } 1125 1126 // set attributes 1127 setAttributes(inputClass, params.inputAttributes); 1128 1129 // set class 1130 inputContainer.className = swalClasses[inputClass]; 1131 if (rerender) { 1132 hide(inputContainer); 1133 } 1134 }); 1135 if (params.input) { 1136 if (rerender) { 1137 showInput(params); 1138 } 1139 // set custom class 1140 setCustomClass(params); 1141 } 1142 }; 1143 1144 /** 1145 * @param {SweetAlertOptions} params 1146 */ 1147 const showInput = params => { 1148 if (!params.input) { 1149 return; 1150 } 1151 if (!renderInputType[params.input]) { 1152 error(`Unexpected type of input! Expected ${Object.keys(renderInputType).join(' | ')}, got "${params.input}"`); 1153 return; 1154 } 1155 const inputContainer = getInputContainer(params.input); 1156 if (!inputContainer) { 1157 return; 1158 } 1159 const input = renderInputType[params.input](inputContainer, params); 1160 show(inputContainer); 1161 1162 // input autofocus 1163 if (params.inputAutoFocus) { 1164 setTimeout(() => { 1165 focusInput(input); 1166 }); 1167 } 1168 }; 1169 1170 /** 1171 * @param {HTMLInputElement} input 1172 */ 1173 const removeAttributes = input => { 1174 for (let i = 0; i < input.attributes.length; i++) { 1175 const attrName = input.attributes[i].name; 1176 if (!['id', 'type', 'value', 'style'].includes(attrName)) { 1177 input.removeAttribute(attrName); 1178 } 1179 } 1180 }; 1181 1182 /** 1183 * @param {InputClass} inputClass 1184 * @param {SweetAlertOptions['inputAttributes']} inputAttributes 1185 */ 1186 const setAttributes = (inputClass, inputAttributes) => { 1187 const popup = getPopup(); 1188 if (!popup) { 1189 return; 1190 } 1191 const input = getInput$1(popup, inputClass); 1192 if (!input) { 1193 return; 1194 } 1195 removeAttributes(input); 1196 for (const attr in inputAttributes) { 1197 input.setAttribute(attr, inputAttributes[attr]); 1198 } 1199 }; 1200 1201 /** 1202 * @param {SweetAlertOptions} params 1203 */ 1204 const setCustomClass = params => { 1205 if (!params.input) { 1206 return; 1207 } 1208 const inputContainer = getInputContainer(params.input); 1209 if (inputContainer) { 1210 applyCustomClass(inputContainer, params, 'input'); 1211 } 1212 }; 1213 1214 /** 1215 * @param {HTMLInputElement | HTMLTextAreaElement} input 1216 * @param {SweetAlertOptions} params 1217 */ 1218 const setInputPlaceholder = (input, params) => { 1219 if (!input.placeholder && params.inputPlaceholder) { 1220 input.placeholder = params.inputPlaceholder; 1221 } 1222 }; 1223 1224 /** 1225 * @param {Input} input 1226 * @param {Input} prependTo 1227 * @param {SweetAlertOptions} params 1228 */ 1229 const setInputLabel = (input, prependTo, params) => { 1230 if (params.inputLabel) { 1231 const label = document.createElement('label'); 1232 const labelClass = swalClasses['input-label']; 1233 label.setAttribute('for', input.id); 1234 label.className = labelClass; 1235 if (typeof params.customClass === 'object') { 1236 addClass(label, params.customClass.inputLabel); 1237 } 1238 label.innerText = params.inputLabel; 1239 prependTo.insertAdjacentElement('beforebegin', label); 1240 } 1241 }; 1242 1243 /** 1244 * @param {SweetAlertInput} inputType 1245 * @returns {HTMLElement | undefined} 1246 */ 1247 const getInputContainer = inputType => { 1248 const popup = getPopup(); 1249 if (!popup) { 1250 return; 1251 } 1252 return getDirectChildByClass(popup, swalClasses[(/** @type {SwalClass} */inputType)] || swalClasses.input); 1253 }; 1254 1255 /** 1256 * @param {HTMLInputElement | HTMLOutputElement | HTMLTextAreaElement} input 1257 * @param {SweetAlertOptions['inputValue']} inputValue 1258 */ 1259 const checkAndSetInputValue = (input, inputValue) => { 1260 if (['string', 'number'].includes(typeof inputValue)) { 1261 input.value = `${inputValue}`; 1262 } else if (!isPromise(inputValue)) { 1263 warn(`Unexpected type of inputValue! Expected "string", "number" or "Promise", got "${typeof inputValue}"`); 1264 } 1265 }; 1266 1267 /** @type {Record<SweetAlertInput, (input: Input | HTMLElement, params: SweetAlertOptions) => Input>} */ 1268 const renderInputType = {}; 1269 1270 /** 1271 * @param {HTMLInputElement} input 1272 * @param {SweetAlertOptions} params 1273 * @returns {HTMLInputElement} 1274 */ 1275 renderInputType.text = renderInputType.email = renderInputType.password = renderInputType.number = renderInputType.tel = renderInputType.url = renderInputType.search = renderInputType.date = renderInputType['datetime-local'] = renderInputType.time = renderInputType.week = renderInputType.month = /** @type {(input: Input | HTMLElement, params: SweetAlertOptions) => Input} */ 1276 (input, params) => { 1277 checkAndSetInputValue(input, params.inputValue); 1278 setInputLabel(input, input, params); 1279 setInputPlaceholder(input, params); 1280 input.type = params.input; 1281 return input; 1282 }; 1283 1284 /** 1285 * @param {HTMLInputElement} input 1286 * @param {SweetAlertOptions} params 1287 * @returns {HTMLInputElement} 1288 */ 1289 renderInputType.file = (input, params) => { 1290 setInputLabel(input, input, params); 1291 setInputPlaceholder(input, params); 1292 return input; 1293 }; 1294 1295 /** 1296 * @param {HTMLInputElement} range 1297 * @param {SweetAlertOptions} params 1298 * @returns {HTMLInputElement} 1299 */ 1300 renderInputType.range = (range, params) => { 1301 const rangeInput = range.querySelector('input'); 1302 const rangeOutput = range.querySelector('output'); 1303 checkAndSetInputValue(rangeInput, params.inputValue); 1304 rangeInput.type = params.input; 1305 checkAndSetInputValue(rangeOutput, params.inputValue); 1306 setInputLabel(rangeInput, range, params); 1307 return range; 1308 }; 1309 1310 /** 1311 * @param {HTMLSelectElement} select 1312 * @param {SweetAlertOptions} params 1313 * @returns {HTMLSelectElement} 1314 */ 1315 renderInputType.select = (select, params) => { 1316 select.textContent = ''; 1317 if (params.inputPlaceholder) { 1318 const placeholder = document.createElement('option'); 1319 setInnerHtml(placeholder, params.inputPlaceholder); 1320 placeholder.value = ''; 1321 placeholder.disabled = true; 1322 placeholder.selected = true; 1323 select.appendChild(placeholder); 1324 } 1325 setInputLabel(select, select, params); 1326 return select; 1327 }; 1328 1329 /** 1330 * @param {HTMLInputElement} radio 1331 * @returns {HTMLInputElement} 1332 */ 1333 renderInputType.radio = radio => { 1334 radio.textContent = ''; 1335 return radio; 1336 }; 1337 1338 /** 1339 * @param {HTMLLabelElement} checkboxContainer 1340 * @param {SweetAlertOptions} params 1341 * @returns {HTMLInputElement} 1342 */ 1343 renderInputType.checkbox = (checkboxContainer, params) => { 1344 const checkbox = getInput$1(getPopup(), 'checkbox'); 1345 checkbox.value = '1'; 1346 checkbox.checked = Boolean(params.inputValue); 1347 const label = checkboxContainer.querySelector('span'); 1348 setInnerHtml(label, params.inputPlaceholder || params.inputLabel); 1349 return checkbox; 1350 }; 1351 1352 /** 1353 * @param {HTMLTextAreaElement} textarea 1354 * @param {SweetAlertOptions} params 1355 * @returns {HTMLTextAreaElement} 1356 */ 1357 renderInputType.textarea = (textarea, params) => { 1358 checkAndSetInputValue(textarea, params.inputValue); 1359 setInputPlaceholder(textarea, params); 1360 setInputLabel(textarea, textarea, params); 1361 1362 /** 1363 * @param {HTMLElement} el 1364 * @returns {number} 1365 */ 1366 const getMargin = el => parseInt(window.getComputedStyle(el).marginLeft) + parseInt(window.getComputedStyle(el).marginRight); 1367 1368 // https://github.com/sweetalert2/sweetalert2/issues/2291 1369 setTimeout(() => { 1370 // https://github.com/sweetalert2/sweetalert2/issues/1699 1371 if ('MutationObserver' in window) { 1372 const initialPopupWidth = parseInt(window.getComputedStyle(getPopup()).width); 1373 const textareaResizeHandler = () => { 1374 // check if texarea is still in document (i.e. popup wasn't closed in the meantime) 1375 if (!document.body.contains(textarea)) { 1376 return; 1377 } 1378 const textareaWidth = textarea.offsetWidth + getMargin(textarea); 1379 if (textareaWidth > initialPopupWidth) { 1380 getPopup().style.width = `${textareaWidth}px`; 1381 } else { 1382 applyNumericalStyle(getPopup(), 'width', params.width); 1383 } 1384 }; 1385 new MutationObserver(textareaResizeHandler).observe(textarea, { 1386 attributes: true, 1387 attributeFilter: ['style'] 1388 }); 1389 } 1390 }); 1391 return textarea; 1392 }; 1393 1394 /** 1395 * @param {SweetAlert} instance 1396 * @param {SweetAlertOptions} params 1397 */ 1398 const renderContent = (instance, params) => { 1399 const htmlContainer = getHtmlContainer(); 1400 if (!htmlContainer) { 1401 return; 1402 } 1403 showWhenInnerHtmlPresent(htmlContainer); 1404 applyCustomClass(htmlContainer, params, 'htmlContainer'); 1405 1406 // Content as HTML 1407 if (params.html) { 1408 parseHtmlToContainer(params.html, htmlContainer); 1409 show(htmlContainer, 'block'); 1410 } 1411 1412 // Content as plain text 1413 else if (params.text) { 1414 htmlContainer.textContent = params.text; 1415 show(htmlContainer, 'block'); 1416 } 1417 1418 // No content 1419 else { 1420 hide(htmlContainer); 1421 } 1422 renderInput(instance, params); 1423 }; 1424 1425 /** 1426 * @param {SweetAlert} instance 1427 * @param {SweetAlertOptions} params 1428 */ 1429 const renderFooter = (instance, params) => { 1430 const footer = getFooter(); 1431 if (!footer) { 1432 return; 1433 } 1434 showWhenInnerHtmlPresent(footer); 1435 toggle(footer, Boolean(params.footer), 'block'); 1436 if (params.footer) { 1437 parseHtmlToContainer(params.footer, footer); 1438 } 1439 1440 // Custom class 1441 applyCustomClass(footer, params, 'footer'); 1442 }; 1443 1444 /** 1445 * @param {SweetAlert} instance 1446 * @param {SweetAlertOptions} params 1447 */ 1448 const renderIcon = (instance, params) => { 1449 const innerParams = privateProps.innerParams.get(instance); 1450 const icon = getIcon(); 1451 if (!icon) { 1452 return; 1453 } 1454 1455 // if the given icon already rendered, apply the styling without re-rendering the icon 1456 if (innerParams && params.icon === innerParams.icon) { 1457 // Custom or default content 1458 setContent(icon, params); 1459 applyStyles(icon, params); 1460 return; 1461 } 1462 if (!params.icon && !params.iconHtml) { 1463 hide(icon); 1464 return; 1465 } 1466 if (params.icon && Object.keys(iconTypes).indexOf(params.icon) === -1) { 1467 error(`Unknown icon! Expected "success", "error", "warning", "info" or "question", got "${params.icon}"`); 1468 hide(icon); 1469 return; 1470 } 1471 show(icon); 1472 1473 // Custom or default content 1474 setContent(icon, params); 1475 applyStyles(icon, params); 1476 1477 // Animate icon 1478 addClass(icon, params.showClass && params.showClass.icon); 1479 1480 // Re-adjust the success icon on system theme change 1481 const colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: dark)'); 1482 colorSchemeQueryList.addEventListener('change', adjustSuccessIconBackgroun
vendor: 4,103 bytes, lines 1482-1620
1482dColor); 1483 }; 1484 1485 /** 1486 * @param {HTMLElement} icon 1487 * @param {SweetAlertOptions} params 1488 */ 1489 const applyStyles = (icon, params) => { 1490 for (const [iconType, iconClassName] of Object.entries(iconTypes)) { 1491 if (params.icon !== iconType) { 1492 removeClass(icon, iconClassName); 1493 } 1494 } 1495 addClass(icon, params.icon && iconTypes[params.icon]); 1496 1497 // Icon color 1498 setColor(icon, params); 1499 1500 // Success icon background color 1501 adjustSuccessIconBackgroundColor(); 1502 1503 // Custom class 1504 applyCustomClass(icon, params, 'icon'); 1505 }; 1506 1507 // Adjust success icon background color to match the popup background color 1508 const adjustSuccessIconBackgroundColor = () => { 1509 const popup = getPopup(); 1510 if (!popup) { 1511 return; 1512 } 1513 const popupBackgroundColor = window.getComputedStyle(popup).getPropertyValue('background-color'); 1514 /** @type {NodeListOf<HTMLElement>} */ 1515 const successIconParts = popup.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix'); 1516 for (let i = 0; i < successIconParts.length; i++) { 1517 successIconParts[i].style.backgroundColor = popupBackgroundColor; 1518 } 1519 }; 1520 1521 /** 1522 * 1523 * @param {SweetAlertOptions} params 1524 * @returns {string} 1525 */ 1526 const successIconHtml = params => ` 1527 ${params.animation ? '<div class="swal2-success-circular-line-left"></div>' : ''} 1528 <span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span> 1529 <div class="swal2-success-ring"></div> 1530 ${params.animation ? '<div class="swal2-success-fix"></div>' : ''} 1531 ${params.animation ? '<div class="swal2-success-circular-line-right"></div>' : ''} 1532`; 1533 const errorIconHtml = ` 1534 <span class="swal2-x-mark"> 1535 <span class="swal2-x-mark-line-left"></span> 1536 <span class="swal2-x-mark-line-right"></span> 1537 </span> 1538`; 1539 1540 /** 1541 * @param {HTMLElement} icon 1542 * @param {SweetAlertOptions} params 1543 */ 1544 const setContent = (icon, params) => { 1545 if (!params.icon && !params.iconHtml) { 1546 return; 1547 } 1548 let oldContent = icon.innerHTML; 1549 let newContent = ''; 1550 if (params.iconHtml) { 1551 newContent = iconContent(params.iconHtml); 1552 } else if (params.icon === 'success') { 1553 newContent = successIconHtml(params); 1554 oldContent = oldContent.replace(/ style=".*?"/g, ''); // undo adjustSuccessIconBackgroundColor() 1555 } else if (params.icon === 'error') { 1556 newContent = errorIconHtml; 1557 } else if (params.icon) { 1558 const defaultIconHtml = { 1559 question: '?', 1560 warning: '!', 1561 info: 'i' 1562 }; 1563 newContent = iconContent(defaultIconHtml[params.icon]); 1564 } 1565 if (oldContent.trim() !== newContent.trim()) { 1566 setInnerHtml(icon, newContent); 1567 } 1568 }; 1569 1570 /** 1571 * @param {HTMLElement} icon 1572 * @param {SweetAlertOptions} params 1573 */ 1574 const setColor = (icon, params) => { 1575 if (!params.iconColor) { 1576 return; 1577 } 1578 icon.style.color = params.iconColor; 1579 icon.style.borderColor = params.iconColor; 1580 for (const sel of ['.swal2-success-line-tip', '.swal2-success-line-long', '.swal2-x-mark-line-left', '.swal2-x-mark-line-right']) { 1581 setStyle(icon, sel, 'background-color', params.iconColor); 1582 } 1583 setStyle(icon, '.swal2-success-ring', 'border-color', params.iconColor); 1584 }; 1585 1586 /** 1587 * @param {string} content 1588 * @returns {string} 1589 */ 1590 const iconContent = content => `<div class="${swalClasses['icon-content']}">${content}</div>`; 1591 1592 /** 1593 * @param {SweetAlert} instance 1594 * @param {SweetAlertOptions} params 1595 */ 1596 const renderImage = (instance, params) => { 1597 const image = getImage(); 1598 if (!image) { 1599 return; 1600 } 1601 if (!params.imageUrl) { 1602 hide(image); 1603 return; 1604 } 1605 show(image, ''); 1606 1607 // Src, alt 1608 image.setAttribute('src', params.imageUrl); 1609 image.setAttribute('alt', params.imageAlt || ''); 1610 1611 // Width, height 1612 applyNumericalStyle(image, 'width', params.imageWidth); 1613 applyNumericalStyle(image, 'height', params.imageHeight); 1614 1615 // Class 1616 image.className = swalClasses.image; 1617 applyCustomClass(image, params, 'image'); 1618 }; 1619 1620 let dragging = false;
vendor: 19,421 bytes, lines 1621-2272
1621 let mousedownX = 0; 1622 let mousedownY = 0; 1623 let initialX = 0; 1624 let initialY = 0; 1625 1626 /** 1627 * @param {HTMLElement} popup 1628 */ 1629 const addDraggableListeners = popup => { 1630 popup.addEventListener('mousedown', down); 1631 document.body.addEventListener('mousemove', move); 1632 popup.addEventListener('mouseup', up); 1633 popup.addEventListener('touchstart', down); 1634 document.body.addEventListener('touchmove', move); 1635 popup.addEventListener('touchend', up); 1636 }; 1637 1638 /** 1639 * @param {HTMLElement} popup 1640 */ 1641 const removeDraggableListeners = popup => { 1642 popup.removeEventListener('mousedown', down); 1643 document.body.removeEventListener('mousemove', move); 1644 popup.removeEventListener('mouseup', up); 1645 popup.removeEventListener('touchstart', down); 1646 document.body.removeEventListener('touchmove', move); 1647 popup.removeEventListener('touchend', up); 1648 }; 1649 1650 /** 1651 * @param {MouseEvent | TouchEvent} event 1652 */ 1653 const down = event => { 1654 const popup = getPopup(); 1655 if (event.target === popup || getIcon().contains(/** @type {HTMLElement} */event.target)) { 1656 dragging = true; 1657 const clientXY = getClientXY(event); 1658 mousedownX = clientXY.clientX; 1659 mousedownY = clientXY.clientY; 1660 initialX = parseInt(popup.style.insetInlineStart) || 0; 1661 initialY = parseInt(popup.style.insetBlockStart) || 0; 1662 addClass(popup, 'swal2-dragging'); 1663 } 1664 }; 1665 1666 /** 1667 * @param {MouseEvent | TouchEvent} event 1668 */ 1669 const move = event => { 1670 const popup = getPopup(); 1671 if (dragging) { 1672 let { 1673 clientX, 1674 clientY 1675 } = getClientXY(event); 1676 popup.style.insetInlineStart = `${initialX + (clientX - mousedownX)}px`; 1677 popup.style.insetBlockStart = `${initialY + (clientY - mousedownY)}px`; 1678 } 1679 }; 1680 const up = () => { 1681 const popup = getPopup(); 1682 dragging = false; 1683 removeClass(popup, 'swal2-dragging'); 1684 }; 1685 1686 /** 1687 * @param {MouseEvent | TouchEvent} event 1688 * @returns {{ clientX: number, clientY: number }} 1689 */ 1690 const getClientXY = event => { 1691 let clientX = 0, 1692 clientY = 0; 1693 if (event.type.startsWith('mouse')) { 1694 clientX = /** @type {MouseEvent} */event.clientX; 1695 clientY = /** @type {MouseEvent} */event.clientY; 1696 } else if (event.type.startsWith('touch')) { 1697 clientX = /** @type {TouchEvent} */event.touches[0].clientX; 1698 clientY = /** @type {TouchEvent} */event.touches[0].clientY; 1699 } 1700 return { 1701 clientX, 1702 clientY 1703 }; 1704 }; 1705 1706 /** 1707 * @param {SweetAlert} instance 1708 * @param {SweetAlertOptions} params 1709 */ 1710 const renderPopup = (instance, params) => { 1711 const container = getContainer(); 1712 const popup = getPopup(); 1713 if (!container || !popup) { 1714 return; 1715 } 1716 1717 // Width 1718 // https://github.com/sweetalert2/sweetalert2/issues/2170 1719 if (params.toast) { 1720 applyNumericalStyle(container, 'width', params.width); 1721 popup.style.width = '100%'; 1722 const loader = getLoader(); 1723 if (loader) { 1724 popup.insertBefore(loader, getIcon()); 1725 } 1726 } else { 1727 applyNumericalStyle(popup, 'width', params.width); 1728 } 1729 1730 // Padding 1731 applyNumericalStyle(popup, 'padding', params.padding); 1732 1733 // Color 1734 if (params.color) { 1735 popup.style.color = params.color; 1736 } 1737 1738 // Background 1739 if (params.background) { 1740 popup.style.background = params.background; 1741 } 1742 hide(getValidationMessage()); 1743 1744 // Classes 1745 addClasses$1(popup, params); 1746 if (params.draggable && !params.toast) { 1747 addClass(popup, swalClasses.draggable); 1748 addDraggableListeners(popup); 1749 } else { 1750 removeClass(popup, swalClasses.draggable); 1751 removeDraggableListeners(popup); 1752 } 1753 }; 1754 1755 /** 1756 * @param {HTMLElement} popup 1757 * @param {SweetAlertOptions} params 1758 */ 1759 const addClasses$1 = (popup, params) => { 1760 const showClass = params.showClass || {}; 1761 // Default Class + showClass when updating Swal.update({}) 1762 popup.className = `${swalClasses.popup} ${isVisible$1(popup) ? showClass.popup : ''}`; 1763 if (params.toast) { 1764 addClass([document.documentElement, document.body], swalClasses['toast-shown']); 1765 addClass(popup, swalClasses.toast); 1766 } else { 1767 addClass(popup, swalClasses.modal); 1768 } 1769 1770 // Custom class 1771 applyCustomClass(popup, params, 'popup'); 1772 // TODO: remove in the next major 1773 if (typeof params.customClass === 'string') { 1774 addClass(popup, params.customClass); 1775 } 1776 1777 // Icon class (#1842) 1778 if (params.icon) { 1779 addClass(popup, swalClasses[`icon-${params.icon}`]); 1780 } 1781 }; 1782 1783 /** 1784 * @param {SweetAlert} instance 1785 * @param {SweetAlertOptions} params 1786 */ 1787 const renderProgressSteps = (instance, params) => { 1788 const progressStepsContainer = getProgressSteps(); 1789 if (!progressStepsContainer) { 1790 return; 1791 } 1792 const { 1793 progressSteps, 1794 currentProgressStep 1795 } = params; 1796 if (!progressSteps || progressSteps.length === 0 || currentProgressStep === undefined) { 1797 hide(progressStepsContainer); 1798 return; 1799 } 1800 show(progressStepsContainer); 1801 progressStepsContainer.textContent = ''; 1802 if (currentProgressStep >= progressSteps.length) { 1803 warn('Invalid currentProgressStep parameter, it should be less than progressSteps.length ' + '(currentProgressStep like JS arrays starts from 0)'); 1804 } 1805 progressSteps.forEach((step, index) => { 1806 const stepEl = createStepElement(step); 1807 progressStepsContainer.appendChild(stepEl); 1808 if (index === currentProgressStep) { 1809 addClass(stepEl, swalClasses['active-progress-step']); 1810 } 1811 if (index !== progressSteps.length - 1) { 1812 const lineEl = createLineElement(params); 1813 progressStepsContainer.appendChild(lineEl); 1814 } 1815 }); 1816 }; 1817 1818 /** 1819 * @param {string} step 1820 * @returns {HTMLLIElement} 1821 */ 1822 const createStepElement = step => { 1823 const stepEl = document.createElement('li'); 1824 addClass(stepEl, swalClasses['progress-step']); 1825 setInnerHtml(stepEl, step); 1826 return stepEl; 1827 }; 1828 1829 /** 1830 * @param {SweetAlertOptions} params 1831 * @returns {HTMLLIElement} 1832 */ 1833 const createLineElement = params => { 1834 const lineEl = document.createElement('li'); 1835 addClass(lineEl, swalClasses['progress-step-line']); 1836 if (params.progressStepsDistance) { 1837 applyNumericalStyle(lineEl, 'width', params.progressStepsDistance); 1838 } 1839 return lineEl; 1840 }; 1841 1842 /** 1843 * @param {SweetAlert} instance 1844 * @param {SweetAlertOptions} params 1845 */ 1846 const renderTitle = (instance, params) => { 1847 const title = getTitle(); 1848 if (!title) { 1849 return; 1850 } 1851 showWhenInnerHtmlPresent(title); 1852 toggle(title, Boolean(params.title || params.titleText), 'block'); 1853 if (params.title) { 1854 parseHtmlToContainer(params.title, title); 1855 } 1856 if (params.titleText) { 1857 title.innerText = params.titleText; 1858 } 1859 1860 // Custom class 1861 applyCustomClass(title, params, 'title'); 1862 }; 1863 1864 /** 1865 * @param {SweetAlert} instance 1866 * @param {SweetAlertOptions} params 1867 */ 1868 const render = (instance, params) => { 1869 renderPopup(instance, params); 1870 renderContainer(instance, params); 1871 renderProgressSteps(instance, params); 1872 renderIcon(instance, params); 1873 renderImage(instance, params); 1874 renderTitle(instance, params); 1875 renderCloseButton(instance, params); 1876 renderContent(instance, params); 1877 renderActions(instance, params); 1878 renderFooter(instance, params); 1879 const popup = getPopup(); 1880 if (typeof params.didRender === 'function' && popup) { 1881 params.didRender(popup); 1882 } 1883 globalState.eventEmitter.emit('didRender', popup); 1884 }; 1885 1886 /* 1887 * Global function to determine if SweetAlert2 popup is shown 1888 */ 1889 const isVisible = () => { 1890 return isVisible$1(getPopup()); 1891 }; 1892 1893 /* 1894 * Global function to click 'Confirm' button 1895 */ 1896 const clickConfirm = () => { 1897 var _dom$getConfirmButton; 1898 return (_dom$getConfirmButton = getConfirmButton()) === null || _dom$getConfirmButton === void 0 ? void 0 : _dom$getConfirmButton.click(); 1899 }; 1900 1901 /* 1902 * Global function to click 'Deny' button 1903 */ 1904 const clickDeny = () => { 1905 var _dom$getDenyButton; 1906 return (_dom$getDenyButton = getDenyButton()) === null || _dom$getDenyButton === void 0 ? void 0 : _dom$getDenyButton.click(); 1907 }; 1908 1909 /* 1910 * Global function to click 'Cancel' button 1911 */ 1912 const clickCancel = () => { 1913 var _dom$getCancelButton; 1914 return (_dom$getCancelButton = getCancelButton()) === null || _dom$getCancelButton === void 0 ? void 0 : _dom$getCancelButton.click(); 1915 }; 1916 1917 /** @type {Record<DismissReason, DismissReason>} */ 1918 const DismissReason = Object.freeze({ 1919 cancel: 'cancel', 1920 backdrop: 'backdrop', 1921 close: 'close', 1922 esc: 'esc', 1923 timer: 'timer' 1924 }); 1925 1926 /** 1927 * @param {GlobalState} globalState 1928 */ 1929 const removeKeydownHandler = globalState => { 1930 if (globalState.keydownTarget && globalState.keydownHandlerAdded) { 1931 globalState.keydownTarget.removeEventListener('keydown', globalState.keydownHandler, { 1932 capture: globalState.keydownListenerCapture 1933 }); 1934 globalState.keydownHandlerAdded = false; 1935 } 1936 }; 1937 1938 /** 1939 * @param {GlobalState} globalState 1940 * @param {SweetAlertOptions} innerParams 1941 * @param {(dismiss: DismissReason) => void} dismissWith 1942 */ 1943 const addKeydownHandler = (globalState, innerParams, dismissWith) => { 1944 removeKeydownHandler(globalState); 1945 if (!innerParams.toast) { 1946 globalState.keydownHandler = e => keydownHandler(innerParams, e, dismissWith); 1947 globalState.keydownTarget = innerParams.keydownListenerCapture ? window : getPopup(); 1948 globalState.keydownListenerCapture = innerParams.keydownListenerCapture; 1949 globalState.keydownTarget.addEventListener('keydown', globalState.keydownHandler, { 1950 capture: globalState.keydownListenerCapture 1951 }); 1952 globalState.keydownHandlerAdded = true; 1953 } 1954 }; 1955 1956 /** 1957 * @param {number} index 1958 * @param {number} increment 1959 */ 1960 const setFocus = (index, increment) => { 1961 var _dom$getPopup; 1962 const focusableElements = getFocusableElements(); 1963 // search for visible elements and select the next possible match 1964 if (focusableElements.length) { 1965 index = index + increment; 1966 1967 // shift + tab when .swal2-popup is focused 1968 if (index === -2) { 1969 index = focusableElements.length - 1; 1970 } 1971 1972 // rollover to first item 1973 if (index === focusableElements.length) { 1974 index = 0; 1975 1976 // go to last item 1977 } else if (index === -1) { 1978 index = focusableElements.length - 1; 1979 } 1980 focusableElements[index].focus(); 1981 return; 1982 } 1983 // no visible focusable elements, focus the popup 1984 (_dom$getPopup = getPopup()) === null || _dom$getPopup === void 0 || _dom$getPopup.focus(); 1985 }; 1986 const arrowKeysNextButton = ['ArrowRight', 'ArrowDown']; 1987 const arrowKeysPreviousButton = ['ArrowLeft', 'ArrowUp']; 1988 1989 /** 1990 * @param {SweetAlertOptions} innerParams 1991 * @param {KeyboardEvent} event 1992 * @param {(dismiss: DismissReason) => void} dismissWith 1993 */ 1994 const keydownHandler = (innerParams, event, dismissWith) => { 1995 if (!innerParams) { 1996 return; // This instance has already been destroyed 1997 } 1998 1999 // Ignore keydown during IME composition 2000 // https://developer.mozilla.org/en-US/docs/Web/API/Document/keydown_event#ignoring_keydown_during_ime_composition 2001 // https://github.com/sweetalert2/sweetalert2/issues/720 2002 // https://github.com/sweetalert2/sweetalert2/issues/2406 2003 if (event.isComposing || event.keyCode === 229) { 2004 return; 2005 } 2006 if (innerParams.stopKeydownPropagation) { 2007 event.stopPropagation(); 2008 } 2009 2010 // ENTER 2011 if (event.key === 'Enter') { 2012 handleEnter(event, innerParams); 2013 } 2014 2015 // TAB 2016 else if (event.key === 'Tab') { 2017 handleTab(event); 2018 } 2019 2020 // ARROWS - switch focus between buttons 2021 else if ([...arrowKeysNextButton, ...arrowKeysPreviousButton].includes(event.key)) { 2022 handleArrows(event.key); 2023 } 2024 2025 // ESC 2026 else if (event.key === 'Escape') { 2027 handleEsc(event, innerParams, dismissWith); 2028 } 2029 }; 2030 2031 /** 2032 * @param {KeyboardEvent} event 2033 * @param {SweetAlertOptions} innerParams 2034 */ 2035 const handleEnter = (event, innerParams) => { 2036 // https://github.com/sweetalert2/sweetalert2/issues/2386 2037 if (!callIfFunction(innerParams.allowEnterKey)) { 2038 return; 2039 } 2040 const input = getInput$1(getPopup(), innerParams.input); 2041 if (event.target && input && event.target instanceof HTMLElement && event.target.outerHTML === input.outerHTML) { 2042 if (['textarea', 'file'].includes(innerParams.input)) { 2043 return; // do not submit 2044 } 2045 clickConfirm(); 2046 event.preventDefault(); 2047 } 2048 }; 2049 2050 /** 2051 * @param {KeyboardEvent} event 2052 */ 2053 const handleTab = event => { 2054 const targetElement = event.target; 2055 const focusableElements = getFocusableElements(); 2056 let btnIndex = -1; 2057 for (let i = 0; i < focusableElements.length; i++) { 2058 if (targetElement === focusableElements[i]) { 2059 btnIndex = i; 2060 break; 2061 } 2062 } 2063 2064 // Cycle to the next button 2065 if (!event.shiftKey) { 2066 setFocus(btnIndex, 1); 2067 } 2068 2069 // Cycle to the prev button 2070 else { 2071 setFocus(btnIndex, -1); 2072 } 2073 event.stopPropagation(); 2074 event.preventDefault(); 2075 }; 2076 2077 /** 2078 * @param {string} key 2079 */ 2080 const handleArrows = key => { 2081 const actions = getActions(); 2082 const confirmButton = getConfirmButton(); 2083 const denyButton = getDenyButton(); 2084 const cancelButton = getCancelButton(); 2085 if (!actions || !confirmButton || !denyButton || !cancelButton) { 2086 return; 2087 } 2088 /** @type HTMLElement[] */ 2089 const buttons = [confirmButton, denyButton, cancelButton]; 2090 if (document.activeElement instanceof HTMLElement && !buttons.includes(document.activeElement)) { 2091 return; 2092 } 2093 const sibling = arrowKeysNextButton.includes(key) ? 'nextElementSibling' : 'previousElementSibling'; 2094 let buttonToFocus = document.activeElement; 2095 if (!buttonToFocus) { 2096 return; 2097 } 2098 for (let i = 0; i < actions.children.length; i++) { 2099 buttonToFocus = buttonToFocus[sibling]; 2100 if (!buttonToFocus) { 2101 return; 2102 } 2103 if (buttonToFocus instanceof HTMLButtonElement && isVisible$1(buttonToFocus)) { 2104 break; 2105 } 2106 } 2107 if (buttonToFocus instanceof HTMLButtonElement) { 2108 buttonToFocus.focus(); 2109 } 2110 }; 2111 2112 /** 2113 * @param {KeyboardEvent} event 2114 * @param {SweetAlertOptions} innerParams 2115 * @param {(dismiss: DismissReason) => void} dismissWith 2116 */ 2117 const handleEsc = (event, innerParams, dismissWith) => { 2118 event.preventDefault(); 2119 if (callIfFunction(innerParams.allowEscapeKey)) { 2120 dismissWith(DismissReason.esc); 2121 } 2122 }; 2123 2124 /** 2125 * This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has. 2126 * For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')` 2127 * This is the approach that Babel will probably take to implement private methods/fields 2128 * https://github.com/tc39/proposal-private-methods 2129 * https://github.com/babel/babel/pull/7555 2130 * Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module* 2131 * then we can use that language feature. 2132 */ 2133 2134 var privateMethods = { 2135 swalPromiseResolve: new WeakMap(), 2136 swalPromiseReject: new WeakMap() 2137 }; 2138 2139 // From https://developer.paciellogroup.com/blog/2018/06/the-current-state-of-modal-dialog-accessibility/ 2140 // Adding aria-hidden="true" to elements outside of the active modal dialog ensures that 2141 // elements not within the active modal dialog will not be surfaced if a user opens a screen 2142 // reader’s list of elements (headings, form controls, landmarks, etc.) in the document. 2143 2144 const setAriaHidden = () => { 2145 const container = getContainer(); 2146 const bodyChildren = Array.from(document.body.children); 2147 bodyChildren.forEach(el => { 2148 if (el.contains(container)) { 2149 return; 2150 } 2151 if (el.hasAttribute('aria-hidden')) { 2152 el.setAttribute('data-previous-aria-hidden', el.getAttribute('aria-hidden') || ''); 2153 } 2154 el.setAttribute('aria-hidden', 'true'); 2155 }); 2156 }; 2157 const unsetAriaHidden = () => { 2158 const bodyChildren = Array.from(document.body.children); 2159 bodyChildren.forEach(el => { 2160 if (el.hasAttribute('data-previous-aria-hidden')) { 2161 el.setAttribute('aria-hidden', el.getAttribute('data-previous-aria-hidden') || ''); 2162 el.removeAttribute('data-previous-aria-hidden'); 2163 } else { 2164 el.removeAttribute('aria-hidden'); 2165 } 2166 }); 2167 }; 2168 2169 // @ts-ignore 2170 const isSafariOrIOS = typeof window !== 'undefined' && !!window.GestureEvent; // true for Safari desktop + all iOS browsers https://stackoverflow.com/a/70585394 2171 2172 /** 2173 * Fix iOS scrolling 2174 * http://stackoverflow.com/q/39626302 2175 */ 2176 const iOSfix = () => { 2177 if (isSafariOrIOS && !hasClass(document.body, swalClasses.iosfix)) { 2178 const offset = document.body.scrollTop; 2179 document.body.style.top = `${offset * -1}px`; 2180 addClass(document.body, swalClasses.iosfix); 2181 lockBodyScroll(); 2182 } 2183 }; 2184 2185 /** 2186 * https://github.com/sweetalert2/sweetalert2/issues/1246 2187 */ 2188 const lockBodyScroll = () => { 2189 const container = getContainer(); 2190 if (!container) { 2191 return; 2192 } 2193 /** @type {boolean} */ 2194 let preventTouchMove; 2195 /** 2196 * @param {TouchEvent} event 2197 */ 2198 container.ontouchstart = event => { 2199 preventTouchMove = shouldPreventTouchMove(event); 2200 }; 2201 /** 2202 * @param {TouchEvent} event 2203 */ 2204 container.ontouchmove = event => { 2205 if (preventTouchMove) { 2206 event.preventDefault(); 2207 event.stopPropagation(); 2208 } 2209 }; 2210 }; 2211 2212 /** 2213 * @param {TouchEvent} event 2214 * @returns {boolean} 2215 */ 2216 const shouldPreventTouchMove = event => { 2217 const target = event.target; 2218 const container = getContainer(); 2219 const htmlContainer = getHtmlContainer(); 2220 if (!container || !htmlContainer) { 2221 return false; 2222 } 2223 if (isStylus(event) || isZoom(event)) { 2224 return false; 2225 } 2226 if (target === container) { 2227 return true; 2228 } 2229 if (!isScrollable(container) && target instanceof HTMLElement && !selfOrParentIsScrollable(target, htmlContainer) && 2230 // #2823 2231 target.tagName !== 'INPUT' && 2232 // #1603 2233 target.tagName !== 'TEXTAREA' && 2234 // #2266 2235 !(isScrollable(htmlContainer) && 2236 // #1944 2237 htmlContainer.contains(target))) { 2238 return true; 2239 } 2240 return false; 2241 }; 2242 2243 /** 2244 * https://github.com/sweetalert2/sweetalert2/issues/1786 2245 * 2246 * @param {object} event 2247 * @returns {boolean} 2248 */ 2249 const isStylus = event => { 2250 return event.touches && event.touches.length && event.touches[0].touchType === 'stylus'; 2251 }; 2252 2253 /** 2254 * https://github.com/sweetalert2/sweetalert2/issues/1891 2255 * 2256 * @param {TouchEvent} event 2257 * @returns {boolean} 2258 */ 2259 const isZoom = event => { 2260 return event.touches && event.touches.length > 1; 2261 }; 2262 const undoIOSfix = () => { 2263 if (hasClass(document.body, swalClasses.iosfix)) { 2264 const offset = parseInt(document.body.style.top, 10); 2265 removeClass(document.body, swalClasses.iosfix); 2266 document.body.style.top = ''; 2267 document.body.scrollTop = offset * -1; 2268 } 2269 }; 2270 2271 /** 2272 * Measure scrollbar width for padding body during modal show/hide
vendor: 5,027 bytes, lines 2273-2424
2273 * https://github.com/twbs/bootstrap/blob/master/js/src/modal.js 2274 * 2275 * @returns {number} 2276 */ 2277 const measureScrollbar = () => { 2278 const scrollDiv = document.createElement('div'); 2279 scrollDiv.className = swalClasses['scrollbar-measure']; 2280 document.body.appendChild(scrollDiv); 2281 const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; 2282 document.body.removeChild(scrollDiv); 2283 return scrollbarWidth; 2284 }; 2285 2286 /** 2287 * Remember state in cases where opening and handling a modal will fiddle with it. 2288 * @type {number | null} 2289 */ 2290 let previousBodyPadding = null; 2291 2292 /** 2293 * @param {string} initialBodyOverflow 2294 */ 2295 const replaceScrollbarWithPadding = initialBodyOverflow => { 2296 // for queues, do not do this more than once 2297 if (previousBodyPadding !== null) { 2298 return; 2299 } 2300 // if the body has overflow 2301 if (document.body.scrollHeight > window.innerHeight || initialBodyOverflow === 'scroll' // https://github.com/sweetalert2/sweetalert2/issues/2663 2302 ) { 2303 // add padding so the content doesn't shift after removal of scrollbar 2304 previousBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right')); 2305 document.body.style.paddingRight = `${previousBodyPadding + measureScrollbar()}px`; 2306 } 2307 }; 2308 const undoReplaceScrollbarWithPadding = () => { 2309 if (previousBodyPadding !== null) { 2310 document.body.style.paddingRight = `${previousBodyPadding}px`; 2311 previousBodyPadding = null; 2312 } 2313 }; 2314 2315 /** 2316 * @param {SweetAlert} instance 2317 * @param {HTMLElement} container 2318 * @param {boolean} returnFocus 2319 * @param {() => void} didClose 2320 */ 2321 function removePopupAndResetState(instance, container, returnFocus, didClose) { 2322 if (isToast()) { 2323 triggerDidCloseAndDispose(instance, didClose); 2324 } else { 2325 restoreActiveElement(returnFocus).then(() => triggerDidCloseAndDispose(instance, didClose)); 2326 removeKeydownHandler(globalState); 2327 } 2328 2329 // workaround for https://github.com/sweetalert2/sweetalert2/issues/2088 2330 // for some reason removing the container in Safari will scroll the document to bottom 2331 if (isSafariOrIOS) { 2332 container.setAttribute('style', 'display:none !important'); 2333 container.removeAttribute('class'); 2334 container.innerHTML = ''; 2335 } else { 2336 container.remove(); 2337 } 2338 if (isModal()) { 2339 undoReplaceScrollbarWithPadding(); 2340 undoIOSfix(); 2341 unsetAriaHidden(); 2342 } 2343 removeBodyClasses(); 2344 } 2345 2346 /** 2347 * Remove SweetAlert2 classes from body 2348 */ 2349 function removeBodyClasses() { 2350 removeClass([document.documentElement, document.body], [swalClasses.shown, swalClasses['height-auto'], swalClasses['no-backdrop'], swalClasses['toast-shown']]); 2351 } 2352 2353 /** 2354 * Instance method to close sweetAlert 2355 * 2356 * @param {SweetAlertResult | undefined} resolveValue 2357 */ 2358 function close(resolveValue) { 2359 resolveValue = prepareResolveValue(resolveValue); 2360 const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this); 2361 const didClose = triggerClosePopup(this); 2362 if (this.isAwaitingPromise) { 2363 // A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335 2364 if (!resolveValue.isDismissed) { 2365 handleAwaitingPromise(this); 2366 swalPromiseResolve(resolveValue); 2367 } 2368 } else if (didClose) { 2369 // Resolve Swal promise 2370 swalPromiseResolve(resolveValue); 2371 } 2372 } 2373 const triggerClosePopup = instance => { 2374 const popup = getPopup(); 2375 if (!popup) { 2376 return false; 2377 } 2378 const innerParams = privateProps.innerParams.get(instance); 2379 if (!innerParams || hasClass(popup, innerParams.hideClass.popup)) { 2380 return false; 2381 } 2382 removeClass(popup, innerParams.showClass.popup); 2383 addClass(popup, innerParams.hideClass.popup); 2384 const backdrop = getContainer(); 2385 removeClass(backdrop, innerParams.showClass.backdrop); 2386 addClass(backdrop, innerParams.hideClass.backdrop); 2387 handlePopupAnimation(instance, popup, innerParams); 2388 return true; 2389 }; 2390 2391 /** 2392 * @param {Error | string} error 2393 */ 2394 function rejectPromise(error) { 2395 const rejectPromise = privateMethods.swalPromiseReject.get(this); 2396 handleAwaitingPromise(this); 2397 if (rejectPromise) { 2398 // Reject Swal promise 2399 rejectPromise(error); 2400 } 2401 } 2402 2403 /** 2404 * @param {SweetAlert} instance 2405 */ 2406 const handleAwaitingPromise = instance => { 2407 if (instance.isAwaitingPromise) { 2408 delete instance.isAwaitingPromise; 2409 // The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335 2410 if (!privateProps.innerParams.get(instance)) { 2411 instance._destroy(); 2412 } 2413 } 2414 }; 2415 2416 /** 2417 * @param {SweetAlertResult | undefined} resolveValue 2418 * @returns {SweetAlertResult} 2419 */ 2420 const prepareResolveValue = resolveValue => { 2421 // When user calls Swal.close() 2422 if (typeof resolveValue === 'undefined') { 2423 return { 2424 isConfirmed: false,
vendor: 15,636 bytes, lines 2425-2913
2425 isDenied: false, 2426 isDismissed: true 2427 }; 2428 } 2429 return Object.assign({ 2430 isConfirmed: false, 2431 isDenied: false, 2432 isDismissed: false 2433 }, resolveValue); 2434 }; 2435 2436 /** 2437 * @param {SweetAlert} instance 2438 * @param {HTMLElement} popup 2439 * @param {SweetAlertOptions} innerParams 2440 */ 2441 const handlePopupAnimation = (instance, popup, innerParams) => { 2442 var _globalState$eventEmi; 2443 const container = getContainer(); 2444 // If animation is supported, animate 2445 const animationIsSupported = hasCssAnimation(popup); 2446 if (typeof innerParams.willClose === 'function') { 2447 innerParams.willClose(popup); 2448 } 2449 (_globalState$eventEmi = globalState.eventEmitter) === null || _globalState$eventEmi === void 0 || _globalState$eventEmi.emit('willClose', popup); 2450 if (animationIsSupported) { 2451 animatePopup(instance, popup, container, innerParams.returnFocus, innerParams.didClose); 2452 } else { 2453 // Otherwise, remove immediately 2454 removePopupAndResetState(instance, container, innerParams.returnFocus, innerParams.didClose); 2455 } 2456 }; 2457 2458 /** 2459 * @param {SweetAlert} instance 2460 * @param {HTMLElement} popup 2461 * @param {HTMLElement} container 2462 * @param {boolean} returnFocus 2463 * @param {() => void} didClose 2464 */ 2465 const animatePopup = (instance, popup, container, returnFocus, didClose) => { 2466 globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(null, instance, container, returnFocus, didClose); 2467 /** 2468 * @param {AnimationEvent | TransitionEvent} e 2469 */ 2470 const swalCloseAnimationFinished = function (e) { 2471 if (e.target === popup) { 2472 var _globalState$swalClos; 2473 (_globalState$swalClos = globalState.swalCloseEventFinishedCallback) === null || _globalState$swalClos === void 0 || _globalState$swalClos.call(globalState); 2474 delete globalState.swalCloseEventFinishedCallback; 2475 popup.removeEventListener('animationend', swalCloseAnimationFinished); 2476 popup.removeEventListener('transitionend', swalCloseAnimationFinished); 2477 } 2478 }; 2479 popup.addEventListener('animationend', swalCloseAnimationFinished); 2480 popup.addEventListener('transitionend', swalCloseAnimationFinished); 2481 }; 2482 2483 /** 2484 * @param {SweetAlert} instance 2485 * @param {() => void} didClose 2486 */ 2487 const triggerDidCloseAndDispose = (instance, didClose) => { 2488 setTimeout(() => { 2489 var _globalState$eventEmi2; 2490 if (typeof didClose === 'function') { 2491 didClose.bind(instance.params)(); 2492 } 2493 (_globalState$eventEmi2 = globalState.eventEmitter) === null || _globalState$eventEmi2 === void 0 || _globalState$eventEmi2.emit('didClose'); 2494 // instance might have been destroyed already 2495 if (instance._destroy) { 2496 instance._destroy(); 2497 } 2498 }); 2499 }; 2500 2501 /** 2502 * Shows loader (spinner), this is useful with AJAX requests. 2503 * By default the loader be shown instead of the "Confirm" button. 2504 * 2505 * @param {HTMLButtonElement | null} [buttonToReplace] 2506 */ 2507 const showLoading = buttonToReplace => { 2508 let popup = getPopup(); 2509 if (!popup) { 2510 new Swal(); 2511 } 2512 popup = getPopup(); 2513 if (!popup) { 2514 return; 2515 } 2516 const loader = getLoader(); 2517 if (isToast()) { 2518 hide(getIcon()); 2519 } else { 2520 replaceButton(popup, buttonToReplace); 2521 } 2522 show(loader); 2523 popup.setAttribute('data-loading', 'true'); 2524 popup.setAttribute('aria-busy', 'true'); 2525 popup.focus(); 2526 }; 2527 2528 /** 2529 * @param {HTMLElement} popup 2530 * @param {HTMLButtonElement | null} [buttonToReplace] 2531 */ 2532 const replaceButton = (popup, buttonToReplace) => { 2533 const actions = getActions(); 2534 const loader = getLoader(); 2535 if (!actions || !loader) { 2536 return; 2537 } 2538 if (!buttonToReplace && isVisible$1(getConfirmButton())) { 2539 buttonToReplace = getConfirmButton(); 2540 } 2541 show(actions); 2542 if (buttonToReplace) { 2543 hide(buttonToReplace); 2544 loader.setAttribute('data-button-to-replace', buttonToReplace.className); 2545 actions.insertBefore(loader, buttonToReplace); 2546 } 2547 addClass([popup, actions], swalClasses.loading); 2548 }; 2549 2550 /** 2551 * @param {SweetAlert} instance 2552 * @param {SweetAlertOptions} params 2553 */ 2554 const handleInputOptionsAndValue = (instance, params) => { 2555 if (params.input === 'select' || params.input === 'radio') { 2556 handleInputOptions(instance, params); 2557 } else if (['text', 'email', 'number', 'tel', 'textarea'].some(i => i === params.input) && (hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))) { 2558 showLoading(getConfirmButton()); 2559 handleInputValue(instance, params); 2560 } 2561 }; 2562 2563 /** 2564 * @param {SweetAlert} instance 2565 * @param {SweetAlertOptions} innerParams 2566 * @returns {SweetAlertInputValue} 2567 */ 2568 const getInputValue = (instance, innerParams) => { 2569 const input = instance.getInput(); 2570 if (!input) { 2571 return null; 2572 } 2573 switch (innerParams.input) { 2574 case 'checkbox': 2575 return getCheckboxValue(input); 2576 case 'radio': 2577 return getRadioValue(input); 2578 case 'file': 2579 return getFileValue(input); 2580 default: 2581 return innerParams.inputAutoTrim ? input.value.trim() : input.value; 2582 } 2583 }; 2584 2585 /** 2586 * @param {HTMLInputElement} input 2587 * @returns {number} 2588 */ 2589 const getCheckboxValue = input => input.checked ? 1 : 0; 2590 2591 /** 2592 * @param {HTMLInputElement} input 2593 * @returns {string | null} 2594 */ 2595 const getRadioValue = input => input.checked ? input.value : null; 2596 2597 /** 2598 * @param {HTMLInputElement} input 2599 * @returns {FileList | File | null} 2600 */ 2601 const getFileValue = input => input.files && input.files.length ? input.getAttribute('multiple') !== null ? input.files : input.files[0] : null; 2602 2603 /** 2604 * @param {SweetAlert} instance 2605 * @param {SweetAlertOptions} params 2606 */ 2607 const handleInputOptions = (instance, params) => { 2608 const popup = getPopup(); 2609 if (!popup) { 2610 return; 2611 } 2612 /** 2613 * @param {*} inputOptions 2614 */ 2615 const processInputOptions = inputOptions => { 2616 if (params.input === 'select') { 2617 populateSelectOptions(popup, formatInputOptions(inputOptions), params); 2618 } else if (params.input === 'radio') { 2619 populateRadioOptions(popup, formatInputOptions(inputOptions), params); 2620 } 2621 }; 2622 if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) { 2623 showLoading(getConfirmButton()); 2624 asPromise(params.inputOptions).then(inputOptions => { 2625 instance.hideLoading(); 2626 processInputOptions(inputOptions); 2627 }); 2628 } else if (typeof params.inputOptions === 'object') { 2629 processInputOptions(params.inputOptions); 2630 } else { 2631 error(`Unexpected type of inputOptions! Expected object, Map or Promise, got ${typeof params.inputOptions}`); 2632 } 2633 }; 2634 2635 /** 2636 * @param {SweetAlert} instance 2637 * @param {SweetAlertOptions} params 2638 */ 2639 const handleInputValue = (instance, params) => { 2640 const input = instance.getInput(); 2641 if (!input) { 2642 return; 2643 } 2644 hide(input); 2645 asPromise(params.inputValue).then(inputValue => { 2646 input.value = params.input === 'number' ? `${parseFloat(inputValue) || 0}` : `${inputValue}`; 2647 show(input); 2648 input.focus(); 2649 instance.hideLoading(); 2650 }).catch(err => { 2651 error(`Error in inputValue promise: ${err}`); 2652 input.value = ''; 2653 show(input); 2654 input.focus(); 2655 instance.hideLoading(); 2656 }); 2657 }; 2658 2659 /** 2660 * @param {HTMLElement} popup 2661 * @param {InputOptionFlattened[]} inputOptions 2662 * @param {SweetAlertOptions} params 2663 */ 2664 function populateSelectOptions(popup, inputOptions, params) { 2665 const select = getDirectChildByClass(popup, swalClasses.select); 2666 if (!select) { 2667 return; 2668 } 2669 /** 2670 * @param {HTMLElement} parent 2671 * @param {string} optionLabel 2672 * @param {string} optionValue 2673 */ 2674 const renderOption = (parent, optionLabel, optionValue) => { 2675 const option = document.createElement('option'); 2676 option.value = optionValue; 2677 setInnerHtml(option, optionLabel); 2678 option.selected = isSelected(optionValue, params.inputValue); 2679 parent.appendChild(option); 2680 }; 2681 inputOptions.forEach(inputOption => { 2682 const optionValue = inputOption[0]; 2683 const optionLabel = inputOption[1]; 2684 // <optgroup> spec: 2685 // https://www.w3.org/TR/html401/interact/forms.html#h-17.6 2686 // "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..." 2687 // check whether this is a <optgroup> 2688 if (Array.isArray(optionLabel)) { 2689 // if it is an array, then it is an <optgroup> 2690 const optgroup = document.createElement('optgroup'); 2691 optgroup.label = optionValue; 2692 optgroup.disabled = false; // not configurable for now 2693 select.appendChild(optgroup); 2694 optionLabel.forEach(o => renderOption(optgroup, o[1], o[0])); 2695 } else { 2696 // case of <option> 2697 renderOption(select, optionLabel, optionValue); 2698 } 2699 }); 2700 select.focus(); 2701 } 2702 2703 /** 2704 * @param {HTMLElement} popup 2705 * @param {InputOptionFlattened[]} inputOptions 2706 * @param {SweetAlertOptions} params 2707 */ 2708 function populateRadioOptions(popup, inputOptions, params) { 2709 const radio = getDirectChildByClass(popup, swalClasses.radio); 2710 if (!radio) { 2711 return; 2712 } 2713 inputOptions.forEach(inputOption => { 2714 const radioValue = inputOption[0]; 2715 const radioLabel = inputOption[1]; 2716 const radioInput = document.createElement('input'); 2717 const radioLabelElement = document.createElement('label'); 2718 radioInput.type = 'radio'; 2719 radioInput.name = swalClasses.radio; 2720 radioInput.value = radioValue; 2721 if (isSelected(radioValue, params.inputValue)) { 2722 radioInput.checked = true; 2723 } 2724 const label = document.createElement('span'); 2725 setInnerHtml(label, radioLabel); 2726 label.className = swalClasses.label; 2727 radioLabelElement.appendChild(radioInput); 2728 radioLabelElement.appendChild(label); 2729 radio.appendChild(radioLabelElement); 2730 }); 2731 const radios = radio.querySelectorAll('input'); 2732 if (radios.length) { 2733 radios[0].focus(); 2734 } 2735 } 2736 2737 /** 2738 * Converts `inputOptions` into an array of `[value, label]`s 2739 * 2740 * @param {*} inputOptions 2741 * @typedef {string[]} InputOptionFlattened 2742 * @returns {InputOptionFlattened[]} 2743 */ 2744 const formatInputOptions = inputOptions => { 2745 /** @type {InputOptionFlattened[]} */ 2746 const result = []; 2747 if (inputOptions instanceof Map) { 2748 inputOptions.forEach((value, key) => { 2749 let valueFormatted = value; 2750 if (typeof valueFormatted === 'object') { 2751 // case of <optgroup> 2752 valueFormatted = formatInputOptions(valueFormatted); 2753 } 2754 result.push([key, valueFormatted]); 2755 }); 2756 } else { 2757 Object.keys(inputOptions).forEach(key => { 2758 let valueFormatted = inputOptions[key]; 2759 if (typeof valueFormatted === 'object') { 2760 // case of <optgroup> 2761 valueFormatted = formatInputOptions(valueFormatted); 2762 } 2763 result.push([key, valueFormatted]); 2764 }); 2765 } 2766 return result; 2767 }; 2768 2769 /** 2770 * @param {string} optionValue 2771 * @param {SweetAlertInputValue} inputValue 2772 * @returns {boolean} 2773 */ 2774 const isSelected = (optionValue, inputValue) => { 2775 return !!inputValue && inputValue.toString() === optionValue.toString(); 2776 }; 2777 2778 /** 2779 * @param {SweetAlert} instance 2780 */ 2781 const handleConfirmButtonClick = instance => { 2782 const innerParams = privateProps.innerParams.get(instance); 2783 instance.disableButtons(); 2784 if (innerParams.input) { 2785 handleConfirmOrDenyWithInput(instance, 'confirm'); 2786 } else { 2787 confirm(instance, true); 2788 } 2789 }; 2790 2791 /** 2792 * @param {SweetAlert} instance 2793 */ 2794 const handleDenyButtonClick = instance => { 2795 const innerParams = privateProps.innerParams.get(instance); 2796 instance.disableButtons(); 2797 if (innerParams.returnInputValueOnDeny) { 2798 handleConfirmOrDenyWithInput(instance, 'deny'); 2799 } else { 2800 deny(instance, false); 2801 } 2802 }; 2803 2804 /** 2805 * @param {SweetAlert} instance 2806 * @param {(dismiss: DismissReason) => void} dismissWith 2807 */ 2808 const handleCancelButtonClick = (instance, dismissWith) => { 2809 instance.disableButtons(); 2810 dismissWith(DismissReason.cancel); 2811 }; 2812 2813 /** 2814 * @param {SweetAlert} instance 2815 * @param {'confirm' | 'deny'} type 2816 */ 2817 const handleConfirmOrDenyWithInput = (instance, type) => { 2818 const innerParams = privateProps.innerParams.get(instance); 2819 if (!innerParams.input) { 2820 error(`The "input" parameter is needed to be set when using returnInputValueOn${capitalizeFirstLetter(type)}`); 2821 return; 2822 } 2823 const input = instance.getInput(); 2824 const inputValue = getInputValue(instance, innerParams); 2825 if (innerParams.inputValidator) { 2826 handleInputValidator(instance, inputValue, type); 2827 } else if (input && !input.checkValidity()) { 2828 instance.enableButtons(); 2829 instance.showValidationMessage(innerParams.validationMessage || input.validationMessage); 2830 } else if (type === 'deny') { 2831 deny(instance, inputValue); 2832 } else { 2833 confirm(instance, inputValue); 2834 } 2835 }; 2836 2837 /** 2838 * @param {SweetAlert} instance 2839 * @param {SweetAlertInputValue} inputValue 2840 * @param {'confirm' | 'deny'} type 2841 */ 2842 const handleInputValidator = (instance, inputValue, type) => { 2843 const innerParams = privateProps.innerParams.get(instance); 2844 instance.disableInput(); 2845 const validationPromise = Promise.resolve().then(() => asPromise(innerParams.inputValidator(inputValue, innerParams.validationMessage))); 2846 validationPromise.then(validationMessage => { 2847 instance.enableButtons(); 2848 instance.enableInput(); 2849 if (validationMessage) { 2850 instance.showValidationMessage(validationMessage); 2851 } else if (type === 'deny') { 2852 deny(instance, inputValue); 2853 } else { 2854 confirm(instance, inputValue); 2855 } 2856 }); 2857 }; 2858 2859 /** 2860 * @param {SweetAlert} instance 2861 * @param {*} value 2862 */ 2863 const deny = (instance, value) => { 2864 const innerParams = privateProps.innerParams.get(instance || undefined); 2865 if (innerParams.showLoaderOnDeny) { 2866 showLoading(getDenyButton()); 2867 } 2868 if (innerParams.preDeny) { 2869 instance.isAwaitingPromise = true; // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preDeny's promise is received 2870 const preDenyPromise = Promise.resolve().then(() => asPromise(innerParams.preDeny(value, innerParams.validationMessage))); 2871 preDenyPromise.then(preDenyValue => { 2872 if (preDenyValue === false) { 2873 instance.hideLoading(); 2874 handleAwaitingPromise(instance); 2875 } else { 2876 instance.close(/** @type SweetAlertResult */{ 2877 isDenied: true, 2878 value: typeof preDenyValue === 'undefined' ? value : preDenyValue 2879 }); 2880 } 2881 }).catch(error => rejectWith(instance || undefined, error)); 2882 } else { 2883 instance.close(/** @type SweetAlertResult */{ 2884 isDenied: true, 2885 value 2886 }); 2887 } 2888 }; 2889 2890 /** 2891 * @param {SweetAlert} instance 2892 * @param {*} value 2893 */ 2894 const succeedWith = (instance, value) => { 2895 instance.close(/** @type SweetAlertResult */{ 2896 isConfirmed: true, 2897 value 2898 }); 2899 }; 2900 2901 /** 2902 * 2903 * @param {SweetAlert} instance 2904 * @param {string} error 2905 */ 2906 const rejectWith = (instance, error) => { 2907 instance.rejectPromise(error); 2908 }; 2909 2910 /** 2911 * 2912 * @param {SweetAlert} instance 2913 * @param {*
vendor: 7,742 bytes, lines 2913-3182
2913} value 2914 */ 2915 const confirm = (instance, value) => { 2916 const innerParams = privateProps.innerParams.get(instance || undefined); 2917 if (innerParams.showLoaderOnConfirm) { 2918 showLoading(); 2919 } 2920 if (innerParams.preConfirm) { 2921 instance.resetValidationMessage(); 2922 instance.isAwaitingPromise = true; // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preConfirm's promise is received 2923 const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage))); 2924 preConfirmPromise.then(preConfirmValue => { 2925 if (isVisible$1(getValidationMessage()) || preConfirmValue === false) { 2926 instance.hideLoading(); 2927 handleAwaitingPromise(instance); 2928 } else { 2929 succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue); 2930 } 2931 }).catch(error => rejectWith(instance || undefined, error)); 2932 } else { 2933 succeedWith(instance, value); 2934 } 2935 }; 2936 2937 /** 2938 * Hides loader and shows back the button which was hidden by .showLoading() 2939 */ 2940 function hideLoading() { 2941 // do nothing if popup is closed 2942 const innerParams = privateProps.innerParams.get(this); 2943 if (!innerParams) { 2944 return; 2945 } 2946 const domCache = privateProps.domCache.get(this); 2947 hide(domCache.loader); 2948 if (isToast()) { 2949 if (innerParams.icon) { 2950 show(getIcon()); 2951 } 2952 } else { 2953 showRelatedButton(domCache); 2954 } 2955 removeClass([domCache.popup, domCache.actions], swalClasses.loading); 2956 domCache.popup.removeAttribute('aria-busy'); 2957 domCache.popup.removeAttribute('data-loading'); 2958 domCache.confirmButton.disabled = false; 2959 domCache.denyButton.disabled = false; 2960 domCache.cancelButton.disabled = false; 2961 } 2962 const showRelatedButton = domCache => { 2963 const buttonToReplace = domCache.popup.getElementsByClassName(domCache.loader.getAttribute('data-button-to-replace')); 2964 if (buttonToReplace.length) { 2965 show(buttonToReplace[0], 'inline-block'); 2966 } else if (allButtonsAreHidden()) { 2967 hide(domCache.actions); 2968 } 2969 }; 2970 2971 /** 2972 * Gets the input DOM node, this method works with input parameter. 2973 * 2974 * @returns {HTMLInputElement | null} 2975 */ 2976 function getInput() { 2977 const innerParams = privateProps.innerParams.get(this); 2978 const domCache = privateProps.domCache.get(this); 2979 if (!domCache) { 2980 return null; 2981 } 2982 return getInput$1(domCache.popup, innerParams.input); 2983 } 2984 2985 /** 2986 * @param {SweetAlert} instance 2987 * @param {string[]} buttons 2988 * @param {boolean} disabled 2989 */ 2990 function setButtonsDisabled(instance, buttons, disabled) { 2991 const domCache = privateProps.domCache.get(instance); 2992 buttons.forEach(button => { 2993 domCache[button].disabled = disabled; 2994 }); 2995 } 2996 2997 /** 2998 * @param {HTMLInputElement | null} input 2999 * @param {boolean} disabled 3000 */ 3001 function setInputDisabled(input, disabled) { 3002 const popup = getPopup(); 3003 if (!popup || !input) { 3004 return; 3005 } 3006 if (input.type === 'radio') { 3007 /** @type {NodeListOf<HTMLInputElement>} */ 3008 const radios = popup.querySelectorAll(`[name="${swalClasses.radio}"]`); 3009 for (let i = 0; i < radios.length; i++) { 3010 radios[i].disabled = disabled; 3011 } 3012 } else { 3013 input.disabled = disabled; 3014 } 3015 } 3016 3017 /** 3018 * Enable all the buttons 3019 * @this {SweetAlert} 3020 */ 3021 function enableButtons() { 3022 setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false); 3023 } 3024 3025 /** 3026 * Disable all the buttons 3027 * @this {SweetAlert} 3028 */ 3029 function disableButtons() { 3030 setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true); 3031 } 3032 3033 /** 3034 * Enable the input field 3035 * @this {SweetAlert} 3036 */ 3037 function enableInput() { 3038 setInputDisabled(this.getInput(), false); 3039 } 3040 3041 /** 3042 * Disable the input field 3043 * @this {SweetAlert} 3044 */ 3045 function disableInput() { 3046 setInputDisabled(this.getInput(), true); 3047 } 3048 3049 /** 3050 * Show block with validation message 3051 * 3052 * @param {string} error 3053 * @this {SweetAlert} 3054 */ 3055 function showValidationMessage(error) { 3056 const domCache = privateProps.domCache.get(this); 3057 const params = privateProps.innerParams.get(this); 3058 setInnerHtml(domCache.validationMessage, error); 3059 domCache.validationMessage.className = swalClasses['validation-message']; 3060 if (params.customClass && params.customClass.validationMessage) { 3061 addClass(domCache.validationMessage, params.customClass.validationMessage); 3062 } 3063 show(domCache.validationMessage); 3064 const input = this.getInput(); 3065 if (input) { 3066 input.setAttribute('aria-invalid', 'true'); 3067 input.setAttribute('aria-describedby', swalClasses['validation-message']); 3068 focusInput(input); 3069 addClass(input, swalClasses.inputerror); 3070 } 3071 } 3072 3073 /** 3074 * Hide block with validation message 3075 * 3076 * @this {SweetAlert} 3077 */ 3078 function resetValidationMessage() { 3079 const domCache = privateProps.domCache.get(this); 3080 if (domCache.validationMessage) { 3081 hide(domCache.validationMessage); 3082 } 3083 const input = this.getInput(); 3084 if (input) { 3085 input.removeAttribute('aria-invalid'); 3086 input.removeAttribute('aria-describedby'); 3087 removeClass(input, swalClasses.inputerror); 3088 } 3089 } 3090 3091 const defaultParams = { 3092 title: '', 3093 titleText: '', 3094 text: '', 3095 html: '', 3096 footer: '', 3097 icon: undefined, 3098 iconColor: undefined, 3099 iconHtml: undefined, 3100 template: undefined, 3101 toast: false, 3102 draggable: false, 3103 animation: true, 3104 theme: 'light', 3105 showClass: { 3106 popup: 'swal2-show', 3107 backdrop: 'swal2-backdrop-show', 3108 icon: 'swal2-icon-show' 3109 }, 3110 hideClass: { 3111 popup: 'swal2-hide', 3112 backdrop: 'swal2-backdrop-hide', 3113 icon: 'swal2-icon-hide' 3114 }, 3115 customClass: {}, 3116 target: 'body', 3117 color: undefined, 3118 backdrop: true, 3119 heightAuto: true, 3120 allowOutsideClick: true, 3121 allowEscapeKey: true, 3122 allowEnterKey: true, 3123 stopKeydownPropagation: true, 3124 keydownListenerCapture: false, 3125 showConfirmButton: true, 3126 showDenyButton: false, 3127 showCancelButton: false, 3128 preConfirm: undefined, 3129 preDeny: undefined, 3130 confirmButtonText: 'OK', 3131 confirmButtonAriaLabel: '', 3132 confirmButtonColor: undefined, 3133 denyButtonText: 'No', 3134 denyButtonAriaLabel: '', 3135 denyButtonColor: undefined, 3136 cancelButtonText: 'Cancel', 3137 cancelButtonAriaLabel: '', 3138 cancelButtonColor: undefined, 3139 buttonsStyling: true, 3140 reverseButtons: false, 3141 focusConfirm: true, 3142 focusDeny: false, 3143 focusCancel: false, 3144 returnFocus: true, 3145 showCloseButton: false, 3146 closeButtonHtml: '×', 3147 closeButtonAriaLabel: 'Close this dialog', 3148 loaderHtml: '', 3149 showLoaderOnConfirm: false, 3150 showLoaderOnDeny: false, 3151 imageUrl: undefined, 3152 imageWidth: undefined, 3153 imageHeight: undefined, 3154 imageAlt: '', 3155 timer: undefined, 3156 timerProgressBar: false, 3157 width: undefined, 3158 padding: undefined, 3159 background: undefined, 3160 input: undefined, 3161 inputPlaceholder: '', 3162 inputLabel: '', 3163 inputValue: '', 3164 inputOptions: {}, 3165 inputAutoFocus: true, 3166 inputAutoTrim: true, 3167 inputAttributes: {}, 3168 inputValidator: undefined, 3169 returnInputValueOnDeny: false, 3170 validationMessage: undefined, 3171 grow: false, 3172 position: 'center', 3173 progressSteps: [], 3174 currentProgressStep: undefined, 3175 progressStepsDistance: undefined, 3176 willOpen: undefined, 3177 didOpen: undefined, 3178 didRender: undefined, 3179 willClose: undefined, 3180 didClose: undefined, 3181 didDestroy: undefined, 3182 scrollbarPadding: true
vendor: 13,129 bytes, lines 3182-3575
3182, 3183 topLayer: false 3184 }; 3185 const updatableParams = ['allowEscapeKey', 'allowOutsideClick', 'background', 'buttonsStyling', 'cancelButtonAriaLabel', 'cancelButtonColor', 'cancelButtonText', 'closeButtonAriaLabel', 'closeButtonHtml', 'color', 'confirmButtonAriaLabel', 'confirmButtonColor', 'confirmButtonText', 'currentProgressStep', 'customClass', 'denyButtonAriaLabel', 'denyButtonColor', 'denyButtonText', 'didClose', 'didDestroy', 'draggable', 'footer', 'hideClass', 'html', 'icon', 'iconColor', 'iconHtml', 'imageAlt', 'imageHeight', 'imageUrl', 'imageWidth', 'preConfirm', 'preDeny', 'progressSteps', 'returnFocus', 'reverseButtons', 'showCancelButton', 'showCloseButton', 'showConfirmButton', 'showDenyButton', 'text', 'title', 'titleText', 'theme', 'willClose']; 3186 3187 /** @type {Record<string, string | undefined>} */ 3188 const deprecatedParams = { 3189 allowEnterKey: undefined 3190 }; 3191 const toastIncompatibleParams = ['allowOutsideClick', 'allowEnterKey', 'backdrop', 'draggable', 'focusConfirm', 'focusDeny', 'focusCancel', 'returnFocus', 'heightAuto', 'keydownListenerCapture']; 3192 3193 /** 3194 * Is valid parameter 3195 * 3196 * @param {string} paramName 3197 * @returns {boolean} 3198 */ 3199 const isValidParameter = paramName => { 3200 return Object.prototype.hasOwnProperty.call(defaultParams, paramName); 3201 }; 3202 3203 /** 3204 * Is valid parameter for Swal.update() method 3205 * 3206 * @param {string} paramName 3207 * @returns {boolean} 3208 */ 3209 const isUpdatableParameter = paramName => { 3210 return updatableParams.indexOf(paramName) !== -1; 3211 }; 3212 3213 /** 3214 * Is deprecated parameter 3215 * 3216 * @param {string} paramName 3217 * @returns {string | undefined} 3218 */ 3219 const isDeprecatedParameter = paramName => { 3220 return deprecatedParams[paramName]; 3221 }; 3222 3223 /** 3224 * @param {string} param 3225 */ 3226 const checkIfParamIsValid = param => { 3227 if (!isValidParameter(param)) { 3228 warn(`Unknown parameter "${param}"`); 3229 } 3230 }; 3231 3232 /** 3233 * @param {string} param 3234 */ 3235 const checkIfToastParamIsValid = param => { 3236 if (toastIncompatibleParams.includes(param)) { 3237 warn(`The parameter "${param}" is incompatible with toasts`); 3238 } 3239 }; 3240 3241 /** 3242 * @param {string} param 3243 */ 3244 const checkIfParamIsDeprecated = param => { 3245 const isDeprecated = isDeprecatedParameter(param); 3246 if (isDeprecated) { 3247 warnAboutDeprecation(param, isDeprecated); 3248 } 3249 }; 3250 3251 /** 3252 * Show relevant warnings for given params 3253 * 3254 * @param {SweetAlertOptions} params 3255 */ 3256 const showWarningsForParams = params => { 3257 if (params.backdrop === false && params.allowOutsideClick) { 3258 warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`'); 3259 } 3260 if (params.theme && !['light', 'dark', 'auto', 'minimal', 'borderless', 'bootstrap-4', 'bootstrap-4-light', 'bootstrap-4-dark', 'bootstrap-5', 'bootstrap-5-light', 'bootstrap-5-dark', 'material-ui', 'material-ui-light', 'material-ui-dark', 'embed-iframe', 'bulma', 'bulma-light', 'bulma-dark'].includes(params.theme)) { 3261 warn(`Invalid theme "${params.theme}"`); 3262 } 3263 for (const param in params) { 3264 checkIfParamIsValid(param); 3265 if (params.toast) { 3266 checkIfToastParamIsValid(param); 3267 } 3268 checkIfParamIsDeprecated(param); 3269 } 3270 }; 3271 3272 /** 3273 * Updates popup parameters. 3274 * 3275 * @param {SweetAlertOptions} params 3276 */ 3277 function update(params) { 3278 const container = getContainer(); 3279 const popup = getPopup(); 3280 const innerParams = privateProps.innerParams.get(this); 3281 if (!popup || hasClass(popup, innerParams.hideClass.popup)) { 3282 warn(`You're trying to update the closed or closing popup, that won't work. Use the update() method in preConfirm parameter or show a new popup.`); 3283 return; 3284 } 3285 const validUpdatableParams = filterValidParams(params); 3286 const updatedParams = Object.assign({}, innerParams, validUpdatableParams); 3287 showWarningsForParams(updatedParams); 3288 container.dataset['swal2Theme'] = updatedParams.theme; 3289 render(this, updatedParams); 3290 privateProps.innerParams.set(this, updatedParams); 3291 Object.defineProperties(this, { 3292 params: { 3293 value: Object.assign({}, this.params, params), 3294 writable: false, 3295 enumerable: true 3296 } 3297 }); 3298 } 3299 3300 /** 3301 * @param {SweetAlertOptions} params 3302 * @returns {SweetAlertOptions} 3303 */ 3304 const filterValidParams = params => { 3305 const validUpdatableParams = {}; 3306 Object.keys(params).forEach(param => { 3307 if (isUpdatableParameter(param)) { 3308 validUpdatableParams[param] = params[param]; 3309 } else { 3310 warn(`Invalid parameter to update: ${param}`); 3311 } 3312 }); 3313 return validUpdatableParams; 3314 }; 3315 3316 /** 3317 * Dispose the current SweetAlert2 instance 3318 */ 3319 function _destroy() { 3320 const domCache = privateProps.domCache.get(this); 3321 const innerParams = privateProps.innerParams.get(this); 3322 if (!innerParams) { 3323 disposeWeakMaps(this); // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #2335 3324 return; // This instance has already been destroyed 3325 } 3326 3327 // Check if there is another Swal closing 3328 if (domCache.popup && globalState.swalCloseEventFinishedCallback) { 3329 globalState.swalCloseEventFinishedCallback(); 3330 delete globalState.swalCloseEventFinishedCallback; 3331 } 3332 if (typeof innerParams.didDestroy === 'function') { 3333 innerParams.didDestroy(); 3334 } 3335 globalState.eventEmitter.emit('didDestroy'); 3336 disposeSwal(this); 3337 } 3338 3339 /** 3340 * @param {SweetAlert} instance 3341 */ 3342 const disposeSwal = instance => { 3343 disposeWeakMaps(instance); 3344 // Unset this.params so GC will dispose it (#1569) 3345 delete instance.params; 3346 // Unset globalState props so GC will dispose globalState (#1569) 3347 delete globalState.keydownHandler; 3348 delete globalState.keydownTarget; 3349 // Unset currentInstance 3350 delete globalState.currentInstance; 3351 }; 3352 3353 /** 3354 * @param {SweetAlert} instance 3355 */ 3356 const disposeWeakMaps = instance => { 3357 // If the current instance is awaiting a promise result, we keep the privateMethods to call them once the promise result is retrieved #2335 3358 if (instance.isAwaitingPromise) { 3359 unsetWeakMaps(privateProps, instance); 3360 instance.isAwaitingPromise = true; 3361 } else { 3362 unsetWeakMaps(privateMethods, instance); 3363 unsetWeakMaps(privateProps, instance); 3364 delete instance.isAwaitingPromise; 3365 // Unset instance methods 3366 delete instance.disableButtons; 3367 delete instance.enableButtons; 3368 delete instance.getInput; 3369 delete instance.disableInput; 3370 delete instance.enableInput; 3371 delete instance.hideLoading; 3372 delete instance.disableLoading; 3373 delete instance.showValidationMessage; 3374 delete instance.resetValidationMessage; 3375 delete instance.close; 3376 delete instance.closePopup; 3377 delete instance.closeModal; 3378 delete instance.closeToast; 3379 delete instance.rejectPromise; 3380 delete instance.update; 3381 delete instance._destroy; 3382 } 3383 }; 3384 3385 /** 3386 * @param {object} obj 3387 * @param {SweetAlert} instance 3388 */ 3389 const unsetWeakMaps = (obj, instance) => { 3390 for (const i in obj) { 3391 obj[i].delete(instance); 3392 } 3393 }; 3394 3395 var instanceMethods = /*#__PURE__*/Object.freeze({ 3396 __proto__: null, 3397 _destroy: _destroy, 3398 close: close, 3399 closeModal: close, 3400 closePopup: close, 3401 closeToast: close, 3402 disableButtons: disableButtons, 3403 disableInput: disableInput, 3404 disableLoading: hideLoading, 3405 enableButtons: enableButtons, 3406 enableInput: enableInput, 3407 getInput: getInput, 3408 handleAwaitingPromise: handleAwaitingPromise, 3409 hideLoading: hideLoading, 3410 rejectPromise: rejectPromise, 3411 resetValidationMessage: resetValidationMessage, 3412 showValidationMessage: showValidationMessage, 3413 update: update 3414 }); 3415 3416 /** 3417 * @param {SweetAlertOptions} innerParams 3418 * @param {DomCache} domCache 3419 * @param {(dismiss: DismissReason) => void} dismissWith 3420 */ 3421 const handlePopupClick = (innerParams, domCache, dismissWith) => { 3422 if (innerParams.toast) { 3423 handleToastClick(innerParams, domCache, dismissWith); 3424 } else { 3425 // Ignore click events that had mousedown on the popup but mouseup on the container 3426 // This can happen when the user drags a slider 3427 handleModalMousedown(domCache); 3428 3429 // Ignore click events that had mousedown on the container but mouseup on the popup 3430 handleContainerMousedown(domCache); 3431 handleModalClick(innerParams, domCache, dismissWith); 3432 } 3433 }; 3434 3435 /** 3436 * @param {SweetAlertOptions} innerParams 3437 * @param {DomCache} domCache 3438 * @param {(dismiss: DismissReason) => void} dismissWith 3439 */ 3440 const handleToastClick = (innerParams, domCache, dismissWith) => { 3441 // Closing toast by internal click 3442 domCache.popup.onclick = () => { 3443 if (innerParams && (isAnyButtonShown(innerParams) || innerParams.timer || innerParams.input)) { 3444 return; 3445 } 3446 dismissWith(DismissReason.close); 3447 }; 3448 }; 3449 3450 /** 3451 * @param {SweetAlertOptions} innerParams 3452 * @returns {boolean} 3453 */ 3454 const isAnyButtonShown = innerParams => { 3455 return !!(innerParams.showConfirmButton || innerParams.showDenyButton || innerParams.showCancelButton || innerParams.showCloseButton); 3456 }; 3457 let ignoreOutsideClick = false; 3458 3459 /** 3460 * @param {DomCache} domCache 3461 */ 3462 const handleModalMousedown = domCache => { 3463 domCache.popup.onmousedown = () => { 3464 domCache.container.onmouseup = function (e) { 3465 domCache.container.onmouseup = () => {}; 3466 // We only check if the mouseup target is the container because usually it doesn't 3467 // have any other direct children aside of the popup 3468 if (e.target === domCache.container) { 3469 ignoreOutsideClick = true; 3470 } 3471 }; 3472 }; 3473 }; 3474 3475 /** 3476 * @param {DomCache} domCache 3477 */ 3478 const handleContainerMousedown = domCache => { 3479 domCache.container.onmousedown = e => { 3480 // prevent the modal text from being selected on double click on the container (allowOutsideClick: false) 3481 if (e.target === domCache.container) { 3482 e.preventDefault(); 3483 } 3484 domCache.popup.onmouseup = function (e) { 3485 domCache.popup.onmouseup = () => {}; 3486 // We also need to check if the mouseup target is a child of the popup 3487 if (e.target === domCache.popup || e.target instanceof HTMLElement && domCache.popup.contains(e.target)) { 3488 ignoreOutsideClick = true; 3489 } 3490 }; 3491 }; 3492 }; 3493 3494 /** 3495 * @param {SweetAlertOptions} innerParams 3496 * @param {DomCache} domCache 3497 * @param {(dismiss: DismissReason) => void} dismissWith 3498 */ 3499 const handleModalClick = (innerParams, domCache, dismissWith) => { 3500 domCache.container.onclick = e => { 3501 if (ignoreOutsideClick) { 3502 ignoreOutsideClick = false; 3503 return; 3504 } 3505 if (e.target === domCache.container && callIfFunction(innerParams.allowOutsideClick)) { 3506 dismissWith(DismissReason.backdrop); 3507 } 3508 }; 3509 }; 3510 3511 const isJqueryElement = elem => typeof elem === 'object' && elem.jquery; 3512 const isElement = elem => elem instanceof Element || isJqueryElement(elem); 3513 const argsToParams = args => { 3514 const params = {}; 3515 if (typeof args[0] === 'object' && !isElement(args[0])) { 3516 Object.assign(params, args[0]); 3517 } else { 3518 ['title', 'html', 'icon'].forEach((name, index) => { 3519 const arg = args[index]; 3520 if (typeof arg === 'string' || isElement(arg)) { 3521 params[name] = arg; 3522 } else if (arg !== undefined) { 3523 error(`Unexpected type of ${name}! Expected "string" or "Element", got ${typeof arg}`); 3524 } 3525 }); 3526 } 3527 return params; 3528 }; 3529 3530 /** 3531 * Main method to create a new SweetAlert2 popup 3532 * 3533 * @param {...SweetAlertOptions} args 3534 * @returns {Promise<SweetAlertResult>} 3535 */ 3536 function fire(...args) { 3537 return new this(...args); 3538 } 3539 3540 /** 3541 * Returns an extended version of `Swal` containing `params` as defaults. 3542 * Useful for reusing Swal configuration. 3543 * 3544 * For example: 3545 * 3546 * Before: 3547 * const textPromptOptions = { input: 'text', showCancelButton: true } 3548 * const {value: firstName} = await Swal.fire({ ...textPromptOptions, title: 'What is your first name?' }) 3549 * const {value: lastName} = await Swal.fire({ ...textPromptOptions, title: 'What is your last name?' }) 3550 * 3551 * After: 3552 * const TextPrompt = Swal.mixin({ input: 'text', showCancelButton: true }) 3553 * const {value: firstName} = await TextPrompt('What is your first name?') 3554 * const {value: lastName} = await TextPrompt('What is your last name?') 3555 * 3556 * @param {SweetAlertOptions} mixinParams 3557 * @returns {SweetAlert} 3558 */ 3559 function mixin(mixinParams) { 3560 class MixinSwal extends this { 3561 _main(params, priorityMixinParams) { 3562 return super._main(params, Object.assign({}, mixinParams, priorityMixinParams)); 3563 } 3564 } 3565 // @ts-ignore 3566 return MixinSwal; 3567 } 3568 3569 /** 3570 * If `timer` parameter is set, returns number of milliseconds of timer remained. 3571 * Otherwise, returns undefined. 3572 * 3573 * @returns {number | undefined} 3574 */ 3575 const getTimerLeft = () => {
vendor: 6,258 bytes, lines 3576-3811
3576 return globalState.timeout && globalState.timeout.getTimerLeft(); 3577 }; 3578 3579 /** 3580 * Stop timer. Returns number of milliseconds of timer remained. 3581 * If `timer` parameter isn't set, returns undefined. 3582 * 3583 * @returns {number | undefined} 3584 */ 3585 const stopTimer = () => { 3586 if (globalState.timeout) { 3587 stopTimerProgressBar(); 3588 return globalState.timeout.stop(); 3589 } 3590 }; 3591 3592 /** 3593 * Resume timer. Returns number of milliseconds of timer remained. 3594 * If `timer` parameter isn't set, returns undefined. 3595 * 3596 * @returns {number | undefined} 3597 */ 3598 const resumeTimer = () => { 3599 if (globalState.timeout) { 3600 const remaining = globalState.timeout.start(); 3601 animateTimerProgressBar(remaining); 3602 return remaining; 3603 } 3604 }; 3605 3606 /** 3607 * Resume timer. Returns number of milliseconds of timer remained. 3608 * If `timer` parameter isn't set, returns undefined. 3609 * 3610 * @returns {number | undefined} 3611 */ 3612 const toggleTimer = () => { 3613 const timer = globalState.timeout; 3614 return timer && (timer.running ? stopTimer() : resumeTimer()); 3615 }; 3616 3617 /** 3618 * Increase timer. Returns number of milliseconds of an updated timer. 3619 * If `timer` parameter isn't set, returns undefined. 3620 * 3621 * @param {number} ms 3622 * @returns {number | undefined} 3623 */ 3624 const increaseTimer = ms => { 3625 if (globalState.timeout) { 3626 const remaining = globalState.timeout.increase(ms); 3627 animateTimerProgressBar(remaining, true); 3628 return remaining; 3629 } 3630 }; 3631 3632 /** 3633 * Check if timer is running. Returns true if timer is running 3634 * or false if timer is paused or stopped. 3635 * If `timer` parameter isn't set, returns undefined 3636 * 3637 * @returns {boolean} 3638 */ 3639 const isTimerRunning = () => { 3640 return !!(globalState.timeout && globalState.timeout.isRunning()); 3641 }; 3642 3643 let bodyClickListenerAdded = false; 3644 const clickHandlers = {}; 3645 3646 /** 3647 * @param {string} attr 3648 */ 3649 function bindClickHandler(attr = 'data-swal-template') { 3650 clickHandlers[attr] = this; 3651 if (!bodyClickListenerAdded) { 3652 document.body.addEventListener('click', bodyClickListener); 3653 bodyClickListenerAdded = true; 3654 } 3655 } 3656 const bodyClickListener = event => { 3657 for (let el = event.target; el && el !== document; el = el.parentNode) { 3658 for (const attr in clickHandlers) { 3659 const template = el.getAttribute(attr); 3660 if (template) { 3661 clickHandlers[attr].fire({ 3662 template 3663 }); 3664 return; 3665 } 3666 } 3667 } 3668 }; 3669 3670 // Source: https://gist.github.com/mudge/5830382?permalink_comment_id=2691957#gistcomment-2691957 3671 3672 class EventEmitter { 3673 constructor() { 3674 /** @type {Events} */ 3675 this.events = {}; 3676 } 3677 3678 /** 3679 * @param {string} eventName 3680 * @returns {EventHandlers} 3681 */ 3682 _getHandlersByEventName(eventName) { 3683 if (typeof this.events[eventName] === 'undefined') { 3684 // not Set because we need to keep the FIFO order 3685 // https://github.com/sweetalert2/sweetalert2/pull/2763#discussion_r1748990334 3686 this.events[eventName] = []; 3687 } 3688 return this.events[eventName]; 3689 } 3690 3691 /** 3692 * @param {string} eventName 3693 * @param {EventHandler} eventHandler 3694 */ 3695 on(eventName, eventHandler) { 3696 const currentHandlers = this._getHandlersByEventName(eventName); 3697 if (!currentHandlers.includes(eventHandler)) { 3698 currentHandlers.push(eventHandler); 3699 } 3700 } 3701 3702 /** 3703 * @param {string} eventName 3704 * @param {EventHandler} eventHandler 3705 */ 3706 once(eventName, eventHandler) { 3707 /** 3708 * @param {Array} args 3709 */ 3710 const onceFn = (...args) => { 3711 this.removeListener(eventName, onceFn); 3712 eventHandler.apply(this, args); 3713 }; 3714 this.on(eventName, onceFn); 3715 } 3716 3717 /** 3718 * @param {string} eventName 3719 * @param {Array} args 3720 */ 3721 emit(eventName, ...args) { 3722 this._getHandlersByEventName(eventName).forEach( 3723 /** 3724 * @param {EventHandler} eventHandler 3725 */ 3726 eventHandler => { 3727 try { 3728 eventHandler.apply(this, args); 3729 } catch (error) { 3730 console.error(error); 3731 } 3732 }); 3733 } 3734 3735 /** 3736 * @param {string} eventName 3737 * @param {EventHandler} eventHandler 3738 */ 3739 removeListener(eventName, eventHandler) { 3740 const currentHandlers = this._getHandlersByEventName(eventName); 3741 const index = currentHandlers.indexOf(eventHandler); 3742 if (index > -1) { 3743 currentHandlers.splice(index, 1); 3744 } 3745 } 3746 3747 /** 3748 * @param {string} eventName 3749 */ 3750 removeAllListeners(eventName) { 3751 if (this.events[eventName] !== undefined) { 3752 // https://github.com/sweetalert2/sweetalert2/pull/2763#discussion_r1749239222 3753 this.events[eventName].length = 0; 3754 } 3755 } 3756 reset() { 3757 this.events = {}; 3758 } 3759 } 3760 3761 globalState.eventEmitter = new EventEmitter(); 3762 3763 /** 3764 * @param {string} eventName 3765 * @param {EventHandler} eventHandler 3766 */ 3767 const on = (eventName, eventHandler) => { 3768 globalState.eventEmitter.on(eventName, eventHandler); 3769 }; 3770 3771 /** 3772 * @param {string} eventName 3773 * @param {EventHandler} eventHandler 3774 */ 3775 const once = (eventName, eventHandler) => { 3776 globalState.eventEmitter.once(eventName, eventHandler); 3777 }; 3778 3779 /** 3780 * @param {string} [eventName] 3781 * @param {EventHandler} [eventHandler] 3782 */ 3783 const off = (eventName, eventHandler) => { 3784 // Remove all handlers for all events 3785 if (!eventName) { 3786 globalState.eventEmitter.reset(); 3787 return; 3788 } 3789 if (eventHandler) { 3790 // Remove a specific handler 3791 globalState.eventEmitter.removeListener(eventName, eventHandler); 3792 } else { 3793 // Remove all handlers for a specific event 3794 globalState.eventEmitter.removeAllListeners(eventName); 3795 } 3796 }; 3797 3798 var staticMethods = /*#__PURE__*/Object.freeze({ 3799 __proto__: null, 3800 argsToParams: argsToParams, 3801 bindClickHandler: bindClickHandler, 3802 clickCancel: clickCancel, 3803 clickConfirm: clickConfirm, 3804 clickDeny: clickDeny, 3805 enableLoading: showLoading, 3806 fire: fire, 3807 getActions: getActions, 3808 getCancelButton: getCancelButton, 3809 getCloseButton: getCloseButton, 3810 getConfirmButton: getConfirmButton, 3811 getContainer: getContainer,
vendor: 13,778 bytes, lines 3812-4243
3812 getDenyButton: getDenyButton, 3813 getFocusableElements: getFocusableElements, 3814 getFooter: getFooter, 3815 getHtmlContainer: getHtmlContainer, 3816 getIcon: getIcon, 3817 getIconContent: getIconContent, 3818 getImage: getImage, 3819 getInputLabel: getInputLabel, 3820 getLoader: getLoader, 3821 getPopup: getPopup, 3822 getProgressSteps: getProgressSteps, 3823 getTimerLeft: getTimerLeft, 3824 getTimerProgressBar: getTimerProgressBar, 3825 getTitle: getTitle, 3826 getValidationMessage: getValidationMessage, 3827 increaseTimer: increaseTimer, 3828 isDeprecatedParameter: isDeprecatedParameter, 3829 isLoading: isLoading, 3830 isTimerRunning: isTimerRunning, 3831 isUpdatableParameter: isUpdatableParameter, 3832 isValidParameter: isValidParameter, 3833 isVisible: isVisible, 3834 mixin: mixin, 3835 off: off, 3836 on: on, 3837 once: once, 3838 resumeTimer: resumeTimer, 3839 showLoading: showLoading, 3840 stopTimer: stopTimer, 3841 toggleTimer: toggleTimer 3842 }); 3843 3844 class Timer { 3845 /** 3846 * @param {() => void} callback 3847 * @param {number} delay 3848 */ 3849 constructor(callback, delay) { 3850 this.callback = callback; 3851 this.remaining = delay; 3852 this.running = false; 3853 this.start(); 3854 } 3855 3856 /** 3857 * @returns {number} 3858 */ 3859 start() { 3860 if (!this.running) { 3861 this.running = true; 3862 this.started = new Date(); 3863 this.id = setTimeout(this.callback, this.remaining); 3864 } 3865 return this.remaining; 3866 } 3867 3868 /** 3869 * @returns {number} 3870 */ 3871 stop() { 3872 if (this.started && this.running) { 3873 this.running = false; 3874 clearTimeout(this.id); 3875 this.remaining -= new Date().getTime() - this.started.getTime(); 3876 } 3877 return this.remaining; 3878 } 3879 3880 /** 3881 * @param {number} n 3882 * @returns {number} 3883 */ 3884 increase(n) { 3885 const running = this.running; 3886 if (running) { 3887 this.stop(); 3888 } 3889 this.remaining += n; 3890 if (running) { 3891 this.start(); 3892 } 3893 return this.remaining; 3894 } 3895 3896 /** 3897 * @returns {number} 3898 */ 3899 getTimerLeft() { 3900 if (this.running) { 3901 this.stop(); 3902 this.start(); 3903 } 3904 return this.remaining; 3905 } 3906 3907 /** 3908 * @returns {boolean} 3909 */ 3910 isRunning() { 3911 return this.running; 3912 } 3913 } 3914 3915 const swalStringParams = ['swal-title', 'swal-html', 'swal-footer']; 3916 3917 /** 3918 * @param {SweetAlertOptions} params 3919 * @returns {SweetAlertOptions} 3920 */ 3921 const getTemplateParams = params => { 3922 const template = typeof params.template === 'string' ? (/** @type {HTMLTemplateElement} */document.querySelector(params.template)) : params.template; 3923 if (!template) { 3924 return {}; 3925 } 3926 /** @type {DocumentFragment} */ 3927 const templateContent = template.content; 3928 showWarningsForElements(templateContent); 3929 const result = Object.assign(getSwalParams(templateContent), getSwalFunctionParams(templateContent), getSwalButtons(templateContent), getSwalImage(templateContent), getSwalIcon(templateContent), getSwalInput(templateContent), getSwalStringParams(templateContent, swalStringParams)); 3930 return result; 3931 }; 3932 3933 /** 3934 * @param {DocumentFragment} templateContent 3935 * @returns {Record<string, string | boolean | number>} 3936 */ 3937 const getSwalParams = templateContent => { 3938 /** @type {Record<string, string | boolean | number>} */ 3939 const result = {}; 3940 /** @type {HTMLElement[]} */ 3941 const swalParams = Array.from(templateContent.querySelectorAll('swal-param')); 3942 swalParams.forEach(param => { 3943 showWarningsForAttributes(param, ['name', 'value']); 3944 const paramName = /** @type {keyof SweetAlertOptions} */param.getAttribute('name'); 3945 const value = param.getAttribute('value'); 3946 if (!paramName || !value) { 3947 return; 3948 } 3949 if (typeof defaultParams[paramName] === 'boolean') { 3950 result[paramName] = value !== 'false'; 3951 } else if (typeof defaultParams[paramName] === 'object') { 3952 result[paramName] = JSON.parse(value); 3953 } else { 3954 result[paramName] = value; 3955 } 3956 }); 3957 return result; 3958 }; 3959 3960 /** 3961 * @param {DocumentFragment} templateContent 3962 * @returns {Record<string, () => void>} 3963 */ 3964 const getSwalFunctionParams = templateContent => { 3965 /** @type {Record<string, () => void>} */ 3966 const result = {}; 3967 /** @type {HTMLElement[]} */ 3968 const swalFunctions = Array.from(templateContent.querySelectorAll('swal-function-param')); 3969 swalFunctions.forEach(param => { 3970 const paramName = /** @type {keyof SweetAlertOptions} */param.getAttribute('name'); 3971 const value = param.getAttribute('value'); 3972 if (!paramName || !value) { 3973 return; 3974 } 3975 result[paramName] = new Function(`return ${value}`)(); 3976 }); 3977 return result; 3978 }; 3979 3980 /** 3981 * @param {DocumentFragment} templateContent 3982 * @returns {Record<string, string | boolean>} 3983 */ 3984 const getSwalButtons = templateContent => { 3985 /** @type {Record<string, string | boolean>} */ 3986 const result = {}; 3987 /** @type {HTMLElement[]} */ 3988 const swalButtons = Array.from(templateContent.querySelectorAll('swal-button')); 3989 swalButtons.forEach(button => { 3990 showWarningsForAttributes(button, ['type', 'color', 'aria-label']); 3991 const type = button.getAttribute('type'); 3992 if (!type || !['confirm', 'cancel', 'deny'].includes(type)) { 3993 return; 3994 } 3995 result[`${type}ButtonText`] = button.innerHTML; 3996 result[`show${capitalizeFirstLetter(type)}Button`] = true; 3997 if (button.hasAttribute('color')) { 3998 result[`${type}ButtonColor`] = button.getAttribute('color'); 3999 } 4000 if (button.hasAttribute('aria-label')) { 4001 result[`${type}ButtonAriaLabel`] = button.getAttribute('aria-label'); 4002 } 4003 }); 4004 return result; 4005 }; 4006 4007 /** 4008 * @param {DocumentFragment} templateContent 4009 * @returns {Pick<SweetAlertOptions, 'imageUrl' | 'imageWidth' | 'imageHeight' | 'imageAlt'>} 4010 */ 4011 const getSwalImage = templateContent => { 4012 const result = {}; 4013 /** @type {HTMLElement | null} */ 4014 const image = templateContent.querySelector('swal-image'); 4015 if (image) { 4016 showWarningsForAttributes(image, ['src', 'width', 'height', 'alt']); 4017 if (image.hasAttribute('src')) { 4018 result.imageUrl = image.getAttribute('src') || undefined; 4019 } 4020 if (image.hasAttribute('width')) { 4021 result.imageWidth = image.getAttribute('width') || undefined; 4022 } 4023 if (image.hasAttribute('height')) { 4024 result.imageHeight = image.getAttribute('height') || undefined; 4025 } 4026 if (image.hasAttribute('alt')) { 4027 result.imageAlt = image.getAttribute('alt') || undefined; 4028 } 4029 } 4030 return result; 4031 }; 4032 4033 /** 4034 * @param {DocumentFragment} templateContent 4035 * @returns {object} 4036 */ 4037 const getSwalIcon = templateContent => { 4038 const result = {}; 4039 /** @type {HTMLElement | null} */ 4040 const icon = templateContent.querySelector('swal-icon'); 4041 if (icon) { 4042 showWarningsForAttributes(icon, ['type', 'color']); 4043 if (icon.hasAttribute('type')) { 4044 result.icon = icon.getAttribute('type'); 4045 } 4046 if (icon.hasAttribute('color')) { 4047 result.iconColor = icon.getAttribute('color'); 4048 } 4049 result.iconHtml = icon.innerHTML; 4050 } 4051 return result; 4052 }; 4053 4054 /** 4055 * @param {DocumentFragment} templateContent 4056 * @returns {object} 4057 */ 4058 const getSwalInput = templateContent => { 4059 /** @type {object} */ 4060 const result = {}; 4061 /** @type {HTMLElement | null} */ 4062 const input = templateContent.querySelector('swal-input'); 4063 if (input) { 4064 showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value']); 4065 result.input = input.getAttribute('type') || 'text'; 4066 if (input.hasAttribute('label')) { 4067 result.inputLabel = input.getAttribute('label'); 4068 } 4069 if (input.hasAttribute('placeholder')) { 4070 result.inputPlaceholder = input.getAttribute('placeholder'); 4071 } 4072 if (input.hasAttribute('value')) { 4073 result.inputValue = input.getAttribute('value'); 4074 } 4075 } 4076 /** @type {HTMLElement[]} */ 4077 const inputOptions = Array.from(templateContent.querySelectorAll('swal-input-option')); 4078 if (inputOptions.length) { 4079 result.inputOptions = {}; 4080 inputOptions.forEach(option => { 4081 showWarningsForAttributes(option, ['value']); 4082 const optionValue = option.getAttribute('value'); 4083 if (!optionValue) { 4084 return; 4085 } 4086 const optionName = option.innerHTML; 4087 result.inputOptions[optionValue] = optionName; 4088 }); 4089 } 4090 return result; 4091 }; 4092 4093 /** 4094 * @param {DocumentFragment} templateContent 4095 * @param {string[]} paramNames 4096 * @returns {Record<string, string>} 4097 */ 4098 const getSwalStringParams = (templateContent, paramNames) => { 4099 /** @type {Record<string, string>} */ 4100 const result = {}; 4101 for (const i in paramNames) { 4102 const paramName = paramNames[i]; 4103 /** @type {HTMLElement | null} */ 4104 const tag = templateContent.querySelector(paramName); 4105 if (tag) { 4106 showWarningsForAttributes(tag, []); 4107 result[paramName.replace(/^swal-/, '')] = tag.innerHTML.trim(); 4108 } 4109 } 4110 return result; 4111 }; 4112 4113 /** 4114 * @param {DocumentFragment} templateContent 4115 */ 4116 const showWarningsForElements = templateContent => { 4117 const allowedElements = swalStringParams.concat(['swal-param', 'swal-function-param', 'swal-button', 'swal-image', 'swal-icon', 'swal-input', 'swal-input-option']); 4118 Array.from(templateContent.children).forEach(el => { 4119 const tagName = el.tagName.toLowerCase(); 4120 if (!allowedElements.includes(tagName)) { 4121 warn(`Unrecognized element <${tagName}>`); 4122 } 4123 }); 4124 }; 4125 4126 /** 4127 * @param {HTMLElement} el 4128 * @param {string[]} allowedAttributes 4129 */ 4130 const showWarningsForAttributes = (el, allowedAttributes) => { 4131 Array.from(el.attributes).forEach(attribute => { 4132 if (allowedAttributes.indexOf(attribute.name) === -1) { 4133 warn([`Unrecognized attribute "${attribute.name}" on <${el.tagName.toLowerCase()}>.`, `${allowedAttributes.length ? `Allowed attributes are: ${allowedAttributes.join(', ')}` : 'To set the value, use HTML within the element.'}`]); 4134 } 4135 }); 4136 }; 4137 4138 const SHOW_CLASS_TIMEOUT = 10; 4139 4140 /** 4141 * Open popup, add necessary classes and styles, fix scrollbar 4142 * 4143 * @param {SweetAlertOptions} params 4144 */ 4145 const openPopup = params => { 4146 const container = getContainer(); 4147 const popup = getPopup(); 4148 if (typeof params.willOpen === 'function') { 4149 params.willOpen(popup); 4150 } 4151 globalState.eventEmitter.emit('willOpen', popup); 4152 const bodyStyles = window.getComputedStyle(document.body); 4153 const initialBodyOverflow = bodyStyles.overflowY; 4154 addClasses(container, popup, params); 4155 4156 // scrolling is 'hidden' until animation is done, after that 'auto' 4157 setTimeout(() => { 4158 setScrollingVisibility(container, popup); 4159 }, SHOW_CLASS_TIMEOUT); 4160 if (isModal()) { 4161 fixScrollContainer(container, params.scrollbarPadding, initialBodyOverflow); 4162 setAriaHidden(); 4163 } 4164 if (!isToast() && !globalState.previousActiveElement) { 4165 globalState.previousActiveElement = document.activeElement; 4166 } 4167 if (typeof params.didOpen === 'function') { 4168 setTimeout(() => params.didOpen(popup)); 4169 } 4170 globalState.eventEmitter.emit('didOpen', popup); 4171 }; 4172 4173 /** 4174 * @param {AnimationEvent} event 4175 */ 4176 const swalOpenAnimationFinished = event => { 4177 const popup = getPopup(); 4178 if (event.target !== popup) { 4179 return; 4180 } 4181 const container = getContainer(); 4182 popup.removeEventListener('animationend', swalOpenAnimationFinished); 4183 popup.removeEventListener('transitionend', swalOpenAnimationFinished); 4184 container.style.overflowY = 'auto'; 4185 4186 // no-transition is added in init() in case one swal is opened right after another 4187 removeClass(container, swalClasses['no-transition']); 4188 }; 4189 4190 /** 4191 * @param {HTMLElement} container 4192 * @param {HTMLElement} popup 4193 */ 4194 const setScrollingVisibility = (container, popup) => { 4195 if (hasCssAnimation(popup)) { 4196 container.style.overflowY = 'hidden'; 4197 popup.addEventListener('animationend', swalOpenAnimationFinished); 4198 popup.addEventListener('transitionend', swalOpenAnimationFinished); 4199 } else { 4200 container.style.overflowY = 'auto'; 4201 } 4202 }; 4203 4204 /** 4205 * @param {HTMLElement} container 4206 * @param {boolean} scrollbarPadding 4207 * @param {string} initialBodyOverflow 4208 */ 4209 const fixScrollContainer = (container, scrollbarPadding, initialBodyOverflow) => { 4210 iOSfix(); 4211 if (scrollbarPadding && initialBodyOverflow !== 'hidden') { 4212 replaceScrollbarWithPadding(initialBodyOverflow); 4213 } 4214 4215 // sweetalert2/issues/1247 4216 setTimeout(() => { 4217 container.scrollTop = 0; 4218 }); 4219 }; 4220 4221 /** 4222 * @param {HTMLElement} container 4223 * @param {HTMLElement} popup 4224 * @param {SweetAlertOptions} params 4225 */ 4226 const addClasses = (container, popup, params) => { 4227 addClass(container, params.showClass.backdrop); 4228 if (params.animation) { 4229 // this workaround with opacity is needed for https://github.com/sweetalert2/sweetalert2/issues/2059 4230 popup.style.setProperty('opacity', '0', 'important'); 4231 show(popup, 'grid'); 4232 setTimeout(() => { 4233 // Animate popup right after showing it 4234 addClass(popup, params.showClass.popup); 4235 // and remove the opacity workaround 4236 popup.style.removeProperty('opacity'); 4237 }, SHOW_CLASS_TIMEOUT); // 10ms in order to fix #2062 4238 } else { 4239 show(popup, 'grid'); 4240 } 4241 addClass([document.documentElement, document.body], swalClasses.shown); 4242 if (params.heightAuto && params.backdrop && !params.toast) { 4243 addClass([document.documentElement, document.body], swalClasses['he
vendor: 7,382 bytes, lines 4243-4465
4243ight-auto']); 4244 } 4245 }; 4246 4247 var defaultInputValidators = { 4248 /** 4249 * @param {string} string 4250 * @param {string} [validationMessage] 4251 * @returns {Promise<string | void>} 4252 */ 4253 email: (string, validationMessage) => { 4254 return /^[a-zA-Z0-9.+_'-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]+$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid email address'); 4255 }, 4256 /** 4257 * @param {string} string 4258 * @param {string} [validationMessage] 4259 * @returns {Promise<string | void>} 4260 */ 4261 url: (string, validationMessage) => { 4262 // taken from https://stackoverflow.com/a/3809435 with a small change from #1306 and #2013 4263 return /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/.test(string) ? Promise.resolve() : Promise.resolve(validationMessage || 'Invalid URL'); 4264 } 4265 }; 4266 4267 /** 4268 * @param {SweetAlertOptions} params 4269 */ 4270 function setDefaultInputValidators(params) { 4271 // Use default `inputValidator` for supported input types if not provided 4272 if (params.inputValidator) { 4273 return; 4274 } 4275 if (params.input === 'email') { 4276 params.inputValidator = defaultInputValidators['email']; 4277 } 4278 if (params.input === 'url') { 4279 params.inputValidator = defaultInputValidators['url']; 4280 } 4281 } 4282 4283 /** 4284 * @param {SweetAlertOptions} params 4285 */ 4286 function validateCustomTargetElement(params) { 4287 // Determine if the custom target element is valid 4288 if (!params.target || typeof params.target === 'string' && !document.querySelector(params.target) || typeof params.target !== 'string' && !params.target.appendChild) { 4289 warn('Target parameter is not valid, defaulting to "body"'); 4290 params.target = 'body'; 4291 } 4292 } 4293 4294 /** 4295 * Set type, text and actions on popup 4296 * 4297 * @param {SweetAlertOptions} params 4298 */ 4299 function setParameters(params) { 4300 setDefaultInputValidators(params); 4301 4302 // showLoaderOnConfirm && preConfirm 4303 if (params.showLoaderOnConfirm && !params.preConfirm) { 4304 warn('showLoaderOnConfirm is set to true, but preConfirm is not defined.\n' + 'showLoaderOnConfirm should be used together with preConfirm, see usage example:\n' + 'https://sweetalert2.github.io/#ajax-request'); 4305 } 4306 validateCustomTargetElement(params); 4307 4308 // Replace newlines with <br> in title 4309 if (typeof params.title === 'string') { 4310 params.title = params.title.split('\n').join('<br />'); 4311 } 4312 init(params); 4313 } 4314 4315 /** @type {SweetAlert} */ 4316 let currentInstance; 4317 var _promise = /*#__PURE__*/new WeakMap(); 4318 class SweetAlert { 4319 /** 4320 * @param {...(SweetAlertOptions | string)} args 4321 * @this {SweetAlert} 4322 */ 4323 constructor(...args) { 4324 /** 4325 * @type {Promise<SweetAlertResult>} 4326 */ 4327 _classPrivateFieldInitSpec(this, _promise, void 0); 4328 // Prevent run in Node env 4329 if (typeof window === 'undefined') { 4330 return; 4331 } 4332 currentInstance = this; 4333 4334 // @ts-ignore 4335 const outerParams = Object.freeze(this.constructor.argsToParams(args)); 4336 4337 /** @type {Readonly<SweetAlertOptions>} */ 4338 this.params = outerParams; 4339 4340 /** @type {boolean} */ 4341 this.isAwaitingPromise = false; 4342 _classPrivateFieldSet2(_promise, this, this._main(currentInstance.params)); 4343 } 4344 _main(userParams, mixinParams = {}) { 4345 showWarningsForParams(Object.assign({}, mixinParams, userParams)); 4346 if (globalState.currentInstance) { 4347 const swalPromiseResolve = privateMethods.swalPromiseResolve.get(globalState.currentInstance); 4348 const { 4349 isAwaitingPromise 4350 } = globalState.currentInstance; 4351 globalState.currentInstance._destroy(); 4352 if (!isAwaitingPromise) { 4353 swalPromiseResolve({ 4354 isDismissed: true 4355 }); 4356 } 4357 if (isModal()) { 4358 unsetAriaHidden(); 4359 } 4360 } 4361 globalState.currentInstance = currentInstance; 4362 const innerParams = prepareParams(userParams, mixinParams); 4363 setParameters(innerParams); 4364 Object.freeze(innerParams); 4365 4366 // clear the previous timer 4367 if (globalState.timeout) { 4368 globalState.timeout.stop(); 4369 delete globalState.timeout; 4370 } 4371 4372 // clear the restore focus timeout 4373 clearTimeout(globalState.restoreFocusTimeout); 4374 const domCache = populateDomCache(currentInstance); 4375 render(currentInstance, innerParams); 4376 privateProps.innerParams.set(currentInstance, innerParams); 4377 return swalPromise(currentInstance, domCache, innerParams); 4378 } 4379 4380 // `catch` cannot be the name of a module export, so we define our thenable methods here instead 4381 then(onFulfilled) { 4382 return _classPrivateFieldGet2(_promise, this).then(onFulfilled); 4383 } 4384 finally(onFinally) { 4385 return _classPrivateFieldGet2(_promise, this).finally(onFinally); 4386 } 4387 } 4388 4389 /** 4390 * @param {SweetAlert} instance 4391 * @param {DomCache} domCache 4392 * @param {SweetAlertOptions} innerParams 4393 * @returns {Promise} 4394 */ 4395 const swalPromise = (instance, domCache, innerParams) => { 4396 return new Promise((resolve, reject) => { 4397 // functions to handle all closings/dismissals 4398 /** 4399 * @param {DismissReason} dismiss 4400 */ 4401 const dismissWith = dismiss => { 4402 instance.close({ 4403 isDismissed: true, 4404 dismiss, 4405 isConfirmed: false, 4406 isDenied: false 4407 }); 4408 }; 4409 privateMethods.swalPromiseResolve.set(instance, resolve); 4410 privateMethods.swalPromiseReject.set(instance, reject); 4411 domCache.confirmButton.onclick = () => { 4412 handleConfirmButtonClick(instance); 4413 }; 4414 domCache.denyButton.onclick = () => { 4415 handleDenyButtonClick(instance); 4416 }; 4417 domCache.cancelButton.onclick = () => { 4418 handleCancelButtonClick(instance, dismissWith); 4419 }; 4420 domCache.closeButton.onclick = () => { 4421 dismissWith(DismissReason.close); 4422 }; 4423 handlePopupClick(innerParams, domCache, dismissWith); 4424 addKeydownHandler(globalState, innerParams, dismissWith); 4425 handleInputOptionsAndValue(instance, innerParams); 4426 openPopup(innerParams); 4427 setupTimer(globalState, innerParams, dismissWith); 4428 initFocus(domCache, innerParams); 4429 4430 // Scroll container to top on open (#1247, #1946) 4431 setTimeout(() => { 4432 domCache.container.scrollTop = 0; 4433 }); 4434 }); 4435 }; 4436 4437 /** 4438 * @param {SweetAlertOptions} userParams 4439 * @param {SweetAlertOptions} mixinParams 4440 * @returns {SweetAlertOptions} 4441 */ 4442 const prepareParams = (userParams, mixinParams) => { 4443 const templateParams = getTemplateParams(userParams); 4444 const params = Object.assign({}, defaultParams, mixinParams, templateParams, userParams); // precedence is described in #2131 4445 params.showClass = Object.assign({}, defaultParams.showClass, params.showClass); 4446 params.hideClass = Object.assign({}, defaultParams.hideClass, params.hideClass); 4447 if (params.animation === false) { 4448 params.showClass = { 4449 backdrop: 'swal2-noanimation' 4450 }; 4451 params.hideClass = {}; 4452 } 4453 return params; 4454 }; 4455 4456 /** 4457 * @param {SweetAlert} instance 4458 * @returns {DomCache} 4459 */ 4460 const populateDomCache = instance => { 4461 const domCache = { 4462 popup: getPopup(), 4463 container: getContainer(), 4464 actions: getActions(), 4465 confirmButton: getConfirmButton(),
vendor: 4,528 bytes, lines 4466-4597
4466 denyButton: getDenyButton(), 4467 cancelButton: getCancelButton(), 4468 loader: getLoader(), 4469 closeButton: getCloseButton(), 4470 validationMessage: getValidationMessage(), 4471 progressSteps: getProgressSteps() 4472 }; 4473 privateProps.domCache.set(instance, domCache); 4474 return domCache; 4475 }; 4476 4477 /** 4478 * @param {GlobalState} globalState 4479 * @param {SweetAlertOptions} innerParams 4480 * @param {(dismiss: DismissReason) => void} dismissWith 4481 */ 4482 const setupTimer = (globalState, innerParams, dismissWith) => { 4483 const timerProgressBar = getTimerProgressBar(); 4484 hide(timerProgressBar); 4485 if (innerParams.timer) { 4486 globalState.timeout = new Timer(() => { 4487 dismissWith('timer'); 4488 delete globalState.timeout; 4489 }, innerParams.timer); 4490 if (innerParams.timerProgressBar) { 4491 show(timerProgressBar); 4492 applyCustomClass(timerProgressBar, innerParams, 'timerProgressBar'); 4493 setTimeout(() => { 4494 if (globalState.timeout && globalState.timeout.running) { 4495 // timer can be already stopped or unset at this point 4496 animateTimerProgressBar(innerParams.timer); 4497 } 4498 }); 4499 } 4500 } 4501 }; 4502 4503 /** 4504 * Initialize focus in the popup: 4505 * 4506 * 1. If `toast` is `true`, don't steal focus from the document. 4507 * 2. Else if there is an [autofocus] element, focus it. 4508 * 3. Else if `focusConfirm` is `true` and confirm button is visible, focus it. 4509 * 4. Else if `focusDeny` is `true` and deny button is visible, focus it. 4510 * 5. Else if `focusCancel` is `true` and cancel button is visible, focus it. 4511 * 6. Else focus the first focusable element in a popup (if any). 4512 * 4513 * @param {DomCache} domCache 4514 * @param {SweetAlertOptions} innerParams 4515 */ 4516 const initFocus = (domCache, innerParams) => { 4517 if (innerParams.toast) { 4518 return; 4519 } 4520 // TODO: this is dumb, remove `allowEnterKey` param in the next major version 4521 if (!callIfFunction(innerParams.allowEnterKey)) { 4522 warnAboutDeprecation('allowEnterKey'); 4523 blurActiveElement(); 4524 return; 4525 } 4526 if (focusAutofocus(domCache)) { 4527 return; 4528 } 4529 if (focusButton(domCache, innerParams)) { 4530 return; 4531 } 4532 setFocus(-1, 1); 4533 }; 4534 4535 /** 4536 * @param {DomCache} domCache 4537 * @returns {boolean} 4538 */ 4539 const focusAutofocus = domCache => { 4540 const autofocusElements = Array.from(domCache.popup.querySelectorAll('[autofocus]')); 4541 for (const autofocusElement of autofocusElements) { 4542 if (autofocusElement instanceof HTMLElement && isVisible$1(autofocusElement)) { 4543 autofocusElement.focus(); 4544 return true; 4545 } 4546 } 4547 return false; 4548 }; 4549 4550 /** 4551 * @param {DomCache} domCache 4552 * @param {SweetAlertOptions} innerParams 4553 * @returns {boolean} 4554 */ 4555 const focusButton = (domCache, innerParams) => { 4556 if (innerParams.focusDeny && isVisible$1(domCache.denyButton)) { 4557 domCache.denyButton.focus(); 4558 return true; 4559 } 4560 if (innerParams.focusCancel && isVisible$1(domCache.cancelButton)) { 4561 domCache.cancelButton.focus(); 4562 return true; 4563 } 4564 if (innerParams.focusConfirm && isVisible$1(domCache.confirmButton)) { 4565 domCache.confirmButton.focus(); 4566 return true; 4567 } 4568 return false; 4569 }; 4570 const blurActiveElement = () => { 4571 if (document.activeElement instanceof HTMLElement && typeof document.activeElement.blur === 'function') { 4572 document.activeElement.blur(); 4573 } 4574 }; 4575 4576 // Assign instance methods from src/instanceMethods/*.js to prototype 4577 SweetAlert.prototype.disableButtons = disableButtons; 4578 SweetAlert.prototype.enableButtons = enableButtons; 4579 SweetAlert.prototype.getInput = getInput; 4580 SweetAlert.prototype.disableInput = disableInput; 4581 SweetAlert.prototype.enableInput = enableInput; 4582 SweetAlert.prototype.hideLoading = hideLoading; 4583 SweetAlert.prototype.disableLoading = hideLoading; 4584 SweetAlert.prototype.showValidationMessage = showValidationMessage; 4585 SweetAlert.prototype.resetValidationMessage = resetValidationMessage; 4586 SweetAlert.prototype.close = close; 4587 SweetAlert.prototype.closePopup = close; 4588 SweetAlert.prototype.closeModal = close; 4589 SweetAlert.prototype.closeToast = close; 4590 SweetAlert.prototype.rejectPromise = rejectPromise; 4591 SweetAlert.prototype.update = update; 4592 SweetAlert.prototype._destroy = _destroy; 4593 4594 // Assign static methods from src/staticMethods/*.js to constructor 4595 Object.assign(SweetAlert, staticMethods); 4596 4597 // Proxy to instance methods to constructor, for now, for backwards compatibility
4598 Object.keys(instanceMethods).forEach(key => { 4599 /** 4600 * @param {...(SweetAlertOptions | string | undefined)} args 4601 * @returns {SweetAlertResult | Promise<SweetAlertResult> | undefined} 4602 */ 4603 SweetAlert[key] = function (...args) { 4604 if (currentInstance && currentInstance[key]) { 4605 return currentInstance[key](...args); 4606 } 4607 return null; 4608 }; 4609 }); 4610 SweetAlert.DismissReason = DismissReason; 4611 SweetAlert.version = '11.26.3'; 4612 4613 const Swal = SweetAlert; 4614 // @ts-ignore 4615 Swal.default = Swal; 4616 4617 return Swal; 4618 4619})); 4620if (typeof this !== 'undefined' && this.Sweetalert2){this.swal = this.sweetAlert = this.Swal = this.SweetAlert = this.Sweetalert2}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.