2019-06-16 09:20:59 +00:00
/ * !
2022-02-07 20:05:14 +00:00
* sweetalert2 v11 . 4.0
2019-06-16 09:20:59 +00:00
* Released under the MIT License .
* /
( function ( global , factory ) {
2020-04-01 22:52:43 +00:00
typeof exports === 'object' && typeof module !== 'undefined' ? module . exports = factory ( ) :
typeof define === 'function' && define . amd ? define ( factory ) :
( global = global || self , global . Sweetalert2 = factory ( ) ) ;
} ( this , function ( ) { 'use strict' ;
2022-02-07 20:05:14 +00:00
const consolePrefix = 'SweetAlert2:' ;
2020-04-01 22:52:43 +00:00
/ * *
* Filter the unique values into a new array
* @ param arr
* /
2022-02-07 20:05:14 +00:00
const uniqueArray = arr => {
const result = [ ] ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
for ( let i = 0 ; i < arr . length ; i ++ ) {
2020-04-01 22:52:43 +00:00
if ( result . indexOf ( arr [ i ] ) === - 1 ) {
result . push ( arr [ i ] ) ;
2019-06-16 09:20:59 +00:00
}
}
2020-04-01 22:52:43 +00:00
return result ;
2019-06-16 09:20:59 +00:00
} ;
2020-04-01 22:52:43 +00:00
/ * *
* Capitalize the first letter of a string
2022-02-07 20:05:14 +00:00
* @ param { string } str
* @ returns { string }
2020-04-01 22:52:43 +00:00
* /
2022-02-07 20:05:14 +00:00
const capitalizeFirstLetter = str => str . charAt ( 0 ) . toUpperCase ( ) + str . slice ( 1 ) ;
2020-04-01 22:52:43 +00:00
/ * *
2022-02-07 20:05:14 +00:00
* @ param { NodeList | HTMLCollection | NamedNodeMap } nodeList
* @ returns { array }
2020-04-01 22:52:43 +00:00
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const toArray = nodeList => Array . prototype . slice . call ( nodeList ) ;
2020-04-01 22:52:43 +00:00
/ * *
2022-02-07 20:05:14 +00:00
* Standardize console warnings
* @ param { string | array } message
2020-04-01 22:52:43 +00:00
* /
2022-02-07 20:05:14 +00:00
const warn = message => {
console . warn ( "" . concat ( consolePrefix , " " ) . concat ( typeof message === 'object' ? message . join ( ' ' ) : message ) ) ;
2020-04-01 22:52:43 +00:00
} ;
/ * *
2022-02-07 20:05:14 +00:00
* Standardize console errors
* @ param { string } message
2020-04-01 22:52:43 +00:00
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const error = message => {
2020-04-01 22:52:43 +00:00
console . error ( "" . concat ( consolePrefix , " " ) . concat ( message ) ) ;
} ;
/ * *
* Private global state for ` warnOnce `
* @ type { Array }
* @ private
* /
2022-02-07 20:05:14 +00:00
const previousWarnOnceMessages = [ ] ;
2020-04-01 22:52:43 +00:00
/ * *
* Show a console warning , but only if it hasn ' t already been shown
2022-02-07 20:05:14 +00:00
* @ param { string } message
2020-04-01 22:52:43 +00:00
* /
2022-02-07 20:05:14 +00:00
const warnOnce = message => {
if ( ! previousWarnOnceMessages . includes ( message ) ) {
2020-04-01 22:52:43 +00:00
previousWarnOnceMessages . push ( message ) ;
warn ( message ) ;
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
} ;
/ * *
* Show a one - time console warning about deprecated params / methods
* /
2022-02-07 20:05:14 +00:00
const warnAboutDeprecation = ( deprecatedParam , useInstead ) => {
2020-04-01 22:52:43 +00:00
warnOnce ( "\"" . concat ( deprecatedParam , "\" is deprecated and will be removed in the next major release. Please use \"" ) . concat ( useInstead , "\" instead." ) ) ;
} ;
/ * *
* If ` arg ` is a function , call it ( with no arguments or context ) and return the result .
* Otherwise , just pass the value through
* @ param arg
* /
2022-02-07 20:05:14 +00:00
const callIfFunction = arg => typeof arg === 'function' ? arg ( ) : arg ;
const hasToPromiseFn = arg => arg && typeof arg . toPromise === 'function' ;
const asPromise = arg => hasToPromiseFn ( arg ) ? arg . toPromise ( ) : Promise . resolve ( arg ) ;
const isPromise = arg => arg && Promise . resolve ( arg ) === arg ;
const defaultParams = {
title : '' ,
titleText : '' ,
text : '' ,
html : '' ,
footer : '' ,
icon : undefined ,
iconColor : undefined ,
iconHtml : undefined ,
template : undefined ,
toast : false ,
showClass : {
popup : 'swal2-show' ,
backdrop : 'swal2-backdrop-show' ,
icon : 'swal2-icon-show'
} ,
hideClass : {
popup : 'swal2-hide' ,
backdrop : 'swal2-backdrop-hide' ,
icon : 'swal2-icon-hide'
} ,
customClass : { } ,
target : 'body' ,
color : undefined ,
backdrop : true ,
heightAuto : true ,
allowOutsideClick : true ,
allowEscapeKey : true ,
allowEnterKey : true ,
stopKeydownPropagation : true ,
keydownListenerCapture : false ,
showConfirmButton : true ,
showDenyButton : false ,
showCancelButton : false ,
preConfirm : undefined ,
preDeny : undefined ,
confirmButtonText : 'OK' ,
confirmButtonAriaLabel : '' ,
confirmButtonColor : undefined ,
denyButtonText : 'No' ,
denyButtonAriaLabel : '' ,
denyButtonColor : undefined ,
cancelButtonText : 'Cancel' ,
cancelButtonAriaLabel : '' ,
cancelButtonColor : undefined ,
buttonsStyling : true ,
reverseButtons : false ,
focusConfirm : true ,
focusDeny : false ,
focusCancel : false ,
returnFocus : true ,
showCloseButton : false ,
closeButtonHtml : '×' ,
closeButtonAriaLabel : 'Close this dialog' ,
loaderHtml : '' ,
showLoaderOnConfirm : false ,
showLoaderOnDeny : false ,
imageUrl : undefined ,
imageWidth : undefined ,
imageHeight : undefined ,
imageAlt : '' ,
timer : undefined ,
timerProgressBar : false ,
width : undefined ,
padding : undefined ,
background : undefined ,
input : undefined ,
inputPlaceholder : '' ,
inputLabel : '' ,
inputValue : '' ,
inputOptions : { } ,
inputAutoTrim : true ,
inputAttributes : { } ,
inputValidator : undefined ,
returnInputValueOnDeny : false ,
validationMessage : undefined ,
grow : false ,
position : 'center' ,
progressSteps : [ ] ,
currentProgressStep : undefined ,
progressStepsDistance : undefined ,
willOpen : undefined ,
didOpen : undefined ,
didRender : undefined ,
willClose : undefined ,
didClose : undefined ,
didDestroy : undefined ,
scrollbarPadding : true
2020-06-28 12:03:17 +00:00
} ;
2022-02-07 20:05:14 +00:00
const updatableParams = [ 'allowEscapeKey' , 'allowOutsideClick' , 'background' , 'buttonsStyling' , 'cancelButtonAriaLabel' , 'cancelButtonColor' , 'cancelButtonText' , 'closeButtonAriaLabel' , 'closeButtonHtml' , 'color' , 'confirmButtonAriaLabel' , 'confirmButtonColor' , 'confirmButtonText' , 'currentProgressStep' , 'customClass' , 'denyButtonAriaLabel' , 'denyButtonColor' , 'denyButtonText' , 'didClose' , 'didDestroy' , 'footer' , 'hideClass' , 'html' , 'icon' , 'iconColor' , 'iconHtml' , 'imageAlt' , 'imageHeight' , 'imageUrl' , 'imageWidth' , 'preConfirm' , 'preDeny' , 'progressSteps' , 'returnFocus' , 'reverseButtons' , 'showCancelButton' , 'showCloseButton' , 'showConfirmButton' , 'showDenyButton' , 'text' , 'title' , 'titleText' , 'willClose' ] ;
const deprecatedParams = { } ;
const toastIncompatibleParams = [ 'allowOutsideClick' , 'allowEnterKey' , 'backdrop' , 'focusConfirm' , 'focusDeny' , 'focusCancel' , 'returnFocus' , 'heightAuto' , 'keydownListenerCapture' ] ;
/ * *
* Is valid parameter
* @ param { string } paramName
* /
const isValidParameter = paramName => {
return Object . prototype . hasOwnProperty . call ( defaultParams , paramName ) ;
2020-06-28 12:03:17 +00:00
} ;
2022-02-07 20:05:14 +00:00
/ * *
* Is valid parameter for Swal . update ( ) method
* @ param { string } paramName
* /
const isUpdatableParameter = paramName => {
return updatableParams . indexOf ( paramName ) !== - 1 ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
/ * *
* Is deprecated parameter
* @ param { string } paramName
* /
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const isDeprecatedParameter = paramName => {
return deprecatedParams [ paramName ] ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const checkIfParamIsValid = param => {
if ( ! isValidParameter ( param ) ) {
warn ( "Unknown parameter \"" . concat ( param , "\"" ) ) ;
}
2019-06-16 09:20:59 +00:00
} ;
2022-02-07 20:05:14 +00:00
const checkIfToastParamIsValid = param => {
if ( toastIncompatibleParams . includes ( param ) ) {
warn ( "The parameter \"" . concat ( param , "\" is incompatible with toasts" ) ) ;
}
2019-06-16 09:20:59 +00:00
} ;
2022-02-07 20:05:14 +00:00
const checkIfParamIsDeprecated = param => {
if ( isDeprecatedParameter ( param ) ) {
warnAboutDeprecation ( param , isDeprecatedParameter ( param ) ) ;
}
} ;
/ * *
* Show relevant warnings for given params
*
* @ param params
* /
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const showWarningsForParams = params => {
if ( ! params . backdrop && params . allowOutsideClick ) {
warn ( '"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`' ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
for ( const param in params ) {
checkIfParamIsValid ( param ) ;
if ( params . toast ) {
checkIfToastParamIsValid ( param ) ;
}
checkIfParamIsDeprecated ( param ) ;
}
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
const swalPrefix = 'swal2-' ;
const prefix = items => {
const result = { } ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
for ( const i in items ) {
2020-04-01 22:52:43 +00:00
result [ items [ i ] ] = swalPrefix + items [ i ] ;
}
return result ;
} ;
2022-02-07 20:05:14 +00:00
const swalClasses = prefix ( [ 'container' , 'shown' , 'height-auto' , 'iosfix' , 'popup' , 'modal' , 'no-backdrop' , 'no-transition' , 'toast' , 'toast-shown' , 'show' , 'hide' , 'close' , 'title' , 'html-container' , 'actions' , 'confirm' , 'deny' , 'cancel' , 'default-outline' , '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' ] ) ;
const iconTypes = prefix ( [ 'success' , 'warning' , 'info' , 'question' , 'error' ] ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
/ * *
* Gets the popup container which contains the backdrop and the popup itself .
*
* @ returns { HTMLElement | null }
* /
const getContainer = ( ) => document . body . querySelector ( "." . concat ( swalClasses . container ) ) ;
const elementBySelector = selectorString => {
const container = getContainer ( ) ;
2020-04-01 22:52:43 +00:00
return container ? container . querySelector ( selectorString ) : null ;
} ;
2022-02-07 20:05:14 +00:00
const elementByClass = className => {
2020-04-01 22:52:43 +00:00
return elementBySelector ( "." . concat ( className ) ) ;
} ;
2022-02-07 20:05:14 +00:00
const getPopup = ( ) => elementByClass ( swalClasses . popup ) ;
const getIcon = ( ) => elementByClass ( swalClasses . icon ) ;
const getTitle = ( ) => elementByClass ( swalClasses . title ) ;
const getHtmlContainer = ( ) => elementByClass ( swalClasses [ 'html-container' ] ) ;
const getImage = ( ) => elementByClass ( swalClasses . image ) ;
const getProgressSteps = ( ) => elementByClass ( swalClasses [ 'progress-steps' ] ) ;
const getValidationMessage = ( ) => elementByClass ( swalClasses [ 'validation-message' ] ) ;
const getConfirmButton = ( ) => elementBySelector ( "." . concat ( swalClasses . actions , " ." ) . concat ( swalClasses . confirm ) ) ;
const getDenyButton = ( ) => elementBySelector ( "." . concat ( swalClasses . actions , " ." ) . concat ( swalClasses . deny ) ) ;
const getInputLabel = ( ) => elementByClass ( swalClasses [ 'input-label' ] ) ;
const getLoader = ( ) => elementBySelector ( "." . concat ( swalClasses . loader ) ) ;
const getCancelButton = ( ) => elementBySelector ( "." . concat ( swalClasses . actions , " ." ) . concat ( swalClasses . cancel ) ) ;
const getActions = ( ) => elementByClass ( swalClasses . actions ) ;
const getFooter = ( ) => elementByClass ( swalClasses . footer ) ;
const getTimerProgressBar = ( ) => elementByClass ( swalClasses [ 'timer-progress-bar' ] ) ;
const getCloseButton = ( ) => elementByClass ( swalClasses . close ) ; // https://github.com/jkup/focusable/blob/master/index.js
const focusable = "\n a[href],\n area[href],\n input:not([disabled]),\n select:not([disabled]),\n textarea:not([disabled]),\n button:not([disabled]),\n iframe,\n object,\n embed,\n [tabindex=\"0\"],\n [contenteditable],\n audio[controls],\n video[controls],\n summary\n" ;
const getFocusableElements = ( ) => {
const focusableElementsWithTabindex = toArray ( getPopup ( ) . querySelectorAll ( '[tabindex]:not([tabindex="-1"]):not([tabindex="0"])' ) ) // sort according to tabindex
. sort ( ( a , b ) => {
const tabindexA = parseInt ( a . getAttribute ( 'tabindex' ) ) ;
const tabindexB = parseInt ( b . getAttribute ( 'tabindex' ) ) ;
if ( tabindexA > tabindexB ) {
2020-04-01 22:52:43 +00:00
return 1 ;
2022-02-07 20:05:14 +00:00
} else if ( tabindexA < tabindexB ) {
2020-04-01 22:52:43 +00:00
return - 1 ;
}
return 0 ;
} ) ;
2022-02-07 20:05:14 +00:00
const otherFocusableElements = toArray ( getPopup ( ) . querySelectorAll ( focusable ) ) . filter ( el => el . getAttribute ( 'tabindex' ) !== '-1' ) ;
return uniqueArray ( focusableElementsWithTabindex . concat ( otherFocusableElements ) ) . filter ( el => isVisible ( el ) ) ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
const isModal = ( ) => {
return ! hasClass ( document . body , swalClasses [ 'toast-shown' ] ) && ! hasClass ( document . body , swalClasses [ 'no-backdrop' ] ) ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
const isToast = ( ) => {
return getPopup ( ) && hasClass ( getPopup ( ) , swalClasses . toast ) ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
const isLoading = ( ) => {
2020-04-01 22:52:43 +00:00
return getPopup ( ) . hasAttribute ( 'data-loading' ) ;
} ;
2022-02-07 20:05:14 +00:00
const states = {
2020-04-01 22:52:43 +00:00
previousBodyPadding : null
} ;
2022-02-07 20:05:14 +00:00
/ * *
* Securely set innerHTML of an element
* https : //github.com/sweetalert2/sweetalert2/issues/1926
*
* @ param { HTMLElement } elem
* @ param { string } html
* /
const setInnerHtml = ( elem , html ) => {
elem . textContent = '' ;
2020-04-01 22:52:43 +00:00
if ( html ) {
2022-02-07 20:05:14 +00:00
const parser = new DOMParser ( ) ;
const parsed = parser . parseFromString ( html , "text/html" ) ;
toArray ( parsed . querySelector ( 'head' ) . childNodes ) . forEach ( child => {
2020-04-01 22:52:43 +00:00
elem . appendChild ( child ) ;
} ) ;
2022-02-07 20:05:14 +00:00
toArray ( parsed . querySelector ( 'body' ) . childNodes ) . forEach ( child => {
2020-04-01 22:52:43 +00:00
elem . appendChild ( child ) ;
} ) ;
}
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { HTMLElement } elem
* @ param { string } className
* @ returns { boolean }
* /
const hasClass = ( elem , className ) => {
2020-04-01 22:52:43 +00:00
if ( ! className ) {
return false ;
}
2022-02-07 20:05:14 +00:00
const classList = className . split ( /\s+/ ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
for ( let i = 0 ; i < classList . length ; i ++ ) {
2020-04-01 22:52:43 +00:00
if ( ! elem . classList . contains ( classList [ i ] ) ) {
return false ;
}
}
2019-06-16 09:20:59 +00:00
return true ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const removeCustomClasses = ( elem , params ) => {
toArray ( elem . classList ) . forEach ( className => {
if ( ! Object . values ( swalClasses ) . includes ( className ) && ! Object . values ( iconTypes ) . includes ( className ) && ! Object . values ( params . showClass ) . includes ( className ) ) {
2020-04-01 22:52:43 +00:00
elem . classList . remove ( className ) ;
}
} ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const applyCustomClass = ( elem , params , className ) => {
2020-04-01 22:52:43 +00:00
removeCustomClasses ( elem , params ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( params . customClass && params . customClass [ className ] ) {
if ( typeof params . customClass [ className ] !== 'string' && ! params . customClass [ className ] . forEach ) {
2022-02-07 20:05:14 +00:00
return warn ( "Invalid type of customClass." . concat ( className , "! Expected string or iterable object, got \"" ) . concat ( typeof params . customClass [ className ] , "\"" ) ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
addClass ( elem , params . customClass [ className ] ) ;
}
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { HTMLElement } popup
* @ param { string } inputType
* @ returns { HTMLInputElement | null }
* /
const getInput = ( popup , inputType ) => {
2020-04-01 22:52:43 +00:00
if ( ! inputType ) {
return null ;
}
switch ( inputType ) {
case 'select' :
case 'textarea' :
case 'file' :
2022-02-07 20:05:14 +00:00
return popup . querySelector ( "." . concat ( swalClasses . popup , " > ." ) . concat ( swalClasses [ inputType ] ) ) ;
2020-04-01 22:52:43 +00:00
case 'checkbox' :
2022-02-07 20:05:14 +00:00
return popup . querySelector ( "." . concat ( swalClasses . popup , " > ." ) . concat ( swalClasses . checkbox , " input" ) ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
case 'radio' :
2022-02-07 20:05:14 +00:00
return popup . querySelector ( "." . concat ( swalClasses . popup , " > ." ) . concat ( swalClasses . radio , " input:checked" ) ) || popup . querySelector ( "." . concat ( swalClasses . popup , " > ." ) . concat ( swalClasses . radio , " input:first-child" ) ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
case 'range' :
2022-02-07 20:05:14 +00:00
return popup . querySelector ( "." . concat ( swalClasses . popup , " > ." ) . concat ( swalClasses . range , " input" ) ) ;
2020-04-01 22:52:43 +00:00
default :
2022-02-07 20:05:14 +00:00
return popup . querySelector ( "." . concat ( swalClasses . popup , " > ." ) . concat ( swalClasses . input ) ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
} ;
/ * *
* @ param { HTMLInputElement } input
* /
const focusInput = input => {
2020-04-01 22:52:43 +00:00
input . focus ( ) ; // place cursor at end of text in text input
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( input . type !== 'file' ) {
// http://stackoverflow.com/a/2345915
2022-02-07 20:05:14 +00:00
const val = input . value ;
2020-04-01 22:52:43 +00:00
input . value = '' ;
input . value = val ;
}
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { HTMLElement | HTMLElement [ ] | null } target
* @ param { string | string [ ] } classList
* @ param { boolean } condition
* /
const toggleClass = ( target , classList , condition ) => {
2020-04-01 22:52:43 +00:00
if ( ! target || ! classList ) {
return ;
}
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( typeof classList === 'string' ) {
classList = classList . split ( /\s+/ ) . filter ( Boolean ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
classList . forEach ( className => {
if ( Array . isArray ( target ) ) {
target . forEach ( elem => {
2020-04-01 22:52:43 +00:00
condition ? elem . classList . add ( className ) : elem . classList . remove ( className ) ;
} ) ;
} else {
condition ? target . classList . add ( className ) : target . classList . remove ( className ) ;
}
} ) ;
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { HTMLElement | HTMLElement [ ] | null } target
* @ param { string | string [ ] } classList
* /
const addClass = ( target , classList ) => {
2020-04-01 22:52:43 +00:00
toggleClass ( target , classList , true ) ;
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { HTMLElement | HTMLElement [ ] | null } target
* @ param { string | string [ ] } classList
* /
const removeClass = ( target , classList ) => {
2020-04-01 22:52:43 +00:00
toggleClass ( target , classList , false ) ;
} ;
2022-02-07 20:05:14 +00:00
/ * *
* Get direct child of an element by class name
*
* @ param { HTMLElement } elem
* @ param { string } className
* @ returns { HTMLElement | null }
* /
const getDirectChildByClass = ( elem , className ) => {
const childNodes = toArray ( elem . childNodes ) ;
for ( let i = 0 ; i < childNodes . length ; i ++ ) {
if ( hasClass ( childNodes [ i ] , className ) ) {
return childNodes [ i ] ;
2020-04-01 22:52:43 +00:00
}
}
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { HTMLElement } elem
* @ param { string } property
* @ param { * } value
* /
const applyNumericalStyle = ( elem , property , value ) => {
2020-11-25 09:31:52 +00:00
if ( value === "" . concat ( parseInt ( value ) ) ) {
value = parseInt ( value ) ;
}
2020-04-01 22:52:43 +00:00
if ( value || parseInt ( value ) === 0 ) {
elem . style [ property ] = typeof value === 'number' ? "" . concat ( value , "px" ) : value ;
} else {
elem . style . removeProperty ( property ) ;
}
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { HTMLElement } elem
* @ param { string } display
* /
const show = function ( elem ) {
let display = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : 'flex' ;
2020-04-01 22:52:43 +00:00
elem . style . display = display ;
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { HTMLElement } elem
* /
const hide = elem => {
2020-04-01 22:52:43 +00:00
elem . style . display = 'none' ;
} ;
2022-02-07 20:05:14 +00:00
const setStyle = ( parent , selector , property , value ) => {
const el = parent . querySelector ( selector ) ;
2020-11-24 07:16:03 +00:00
if ( el ) {
el . style [ property ] = value ;
}
} ;
2022-02-07 20:05:14 +00:00
const toggle = ( elem , condition , display ) => {
2020-04-01 22:52:43 +00:00
condition ? show ( elem , display ) : hide ( elem ) ;
} ; // borrowed from jquery $(elem).is(':visible') implementation
2022-02-07 20:05:14 +00:00
const isVisible = elem => ! ! ( elem && ( elem . offsetWidth || elem . offsetHeight || elem . getClientRects ( ) . length ) ) ;
const allButtonsAreHidden = ( ) => ! isVisible ( getConfirmButton ( ) ) && ! isVisible ( getDenyButton ( ) ) && ! isVisible ( getCancelButton ( ) ) ;
const isScrollable = elem => ! ! ( elem . scrollHeight > elem . clientHeight ) ; // borrowed from https://stackoverflow.com/a/46352119
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const hasCssAnimation = elem => {
const style = window . getComputedStyle ( elem ) ;
const animDuration = parseFloat ( style . getPropertyValue ( 'animation-duration' ) || '0' ) ;
const transDuration = parseFloat ( style . getPropertyValue ( 'transition-duration' ) || '0' ) ;
2020-04-01 22:52:43 +00:00
return animDuration > 0 || transDuration > 0 ;
} ;
2022-02-07 20:05:14 +00:00
const animateTimerProgressBar = function ( timer ) {
let reset = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : false ;
const timerProgressBar = getTimerProgressBar ( ) ;
2020-04-01 22:52:43 +00:00
if ( isVisible ( timerProgressBar ) ) {
if ( reset ) {
timerProgressBar . style . transition = 'none' ;
timerProgressBar . style . width = '100%' ;
2019-06-16 09:20:59 +00:00
}
2022-02-07 20:05:14 +00:00
setTimeout ( ( ) => {
2020-04-01 22:52:43 +00:00
timerProgressBar . style . transition = "width " . concat ( timer / 1000 , "s linear" ) ;
timerProgressBar . style . width = '0%' ;
} , 10 ) ;
}
} ;
2022-02-07 20:05:14 +00:00
const stopTimerProgressBar = ( ) => {
const timerProgressBar = getTimerProgressBar ( ) ;
const timerProgressBarWidth = parseInt ( window . getComputedStyle ( timerProgressBar ) . width ) ;
2020-04-01 22:52:43 +00:00
timerProgressBar . style . removeProperty ( 'transition' ) ;
timerProgressBar . style . width = '100%' ;
2022-02-07 20:05:14 +00:00
const timerProgressBarFullWidth = parseInt ( window . getComputedStyle ( timerProgressBar ) . width ) ;
const timerProgressBarPercent = timerProgressBarWidth / timerProgressBarFullWidth * 100 ;
2020-04-01 22:52:43 +00:00
timerProgressBar . style . removeProperty ( 'transition' ) ;
timerProgressBar . style . width = "" . concat ( timerProgressBarPercent , "%" ) ;
} ;
2022-02-07 20:05:14 +00:00
/ * *
* Detect Node env
*
* @ returns { boolean }
* /
const isNodeEnv = ( ) => typeof window === 'undefined' || typeof document === 'undefined' ;
const RESTORE _FOCUS _TIMEOUT = 100 ;
const globalState = { } ;
const focusPreviousActiveElement = ( ) => {
if ( globalState . previousActiveElement && globalState . previousActiveElement . focus ) {
globalState . previousActiveElement . focus ( ) ;
globalState . previousActiveElement = null ;
} else if ( document . body ) {
document . body . focus ( ) ;
}
} ; // Restore previous active (focused) element
const restoreActiveElement = returnFocus => {
return new Promise ( resolve => {
if ( ! returnFocus ) {
return resolve ( ) ;
}
const x = window . scrollX ;
const y = window . scrollY ;
globalState . restoreFocusTimeout = setTimeout ( ( ) => {
focusPreviousActiveElement ( ) ;
resolve ( ) ;
} , RESTORE _FOCUS _TIMEOUT ) ; // issues/900
window . scrollTo ( x , y ) ;
} ) ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
const sweetHTML = "\n <div aria-labelledby=\"" . concat ( swalClasses . title , "\" aria-describedby=\"" ) . concat ( swalClasses [ 'html-container' ] , "\" class=\"" ) . concat ( swalClasses . popup , "\" tabindex=\"-1\">\n <button type=\"button\" class=\"" ) . concat ( swalClasses . close , "\"></button>\n <ul class=\"" ) . concat ( swalClasses [ 'progress-steps' ] , "\"></ul>\n <div class=\"" ) . concat ( swalClasses . icon , "\"></div>\n <img class=\"" ) . concat ( swalClasses . image , "\" />\n <h2 class=\"" ) . concat ( swalClasses . title , "\" id=\"" ) . concat ( swalClasses . title , "\"></h2>\n <div class=\"" ) . concat ( swalClasses [ 'html-container' ] , "\" id=\"" ) . concat ( swalClasses [ 'html-container' ] , "\"></div>\n <input class=\"" ) . concat ( swalClasses . input , "\" />\n <input type=\"file\" class=\"" ) . concat ( swalClasses . file , "\" />\n <div class=\"" ) . concat ( swalClasses . range , "\">\n <input type=\"range\" />\n <output></output>\n </div>\n <select class=\"" ) . concat ( swalClasses . select , "\"></select>\n <div class=\"" ) . concat ( swalClasses . radio , "\"></div>\n <label for=\"" ) . concat ( swalClasses . checkbox , "\" class=\"" ) . concat ( swalClasses . checkbox , "\">\n <input type=\"checkbox\" />\n <span class=\"" ) . concat ( swalClasses . label , "\"></span>\n </label>\n <textarea class=\"" ) . concat ( swalClasses . textarea , "\"></textarea>\n <div class=\"" ) . concat ( swalClasses [ 'validation-message' ] , "\" id=\"" ) . concat ( swalClasses [ 'validation-message' ] , "\"></div>\n <div class=\"" ) . concat ( swalClasses . actions , "\">\n <div class=\"" ) . concat ( swalClasses . loader , "\"></div>\n <button type=\"button\" class=\"" ) . concat ( swalClasses . confirm , "\"></button>\n <button type=\"button\" class=\"" ) . concat ( swalClasses . deny , "\"></button>\n <button type=\"button\" class=\"" ) . concat ( swalClasses . cancel , "\"></button>\n </div>\n <div class=\"" ) . concat ( swalClasses . footer , "\"></div>\n <div class=\"" ) . concat ( swalClasses [ 'timer-progress-bar-container' ] , "\">\n <div class=\"" ) . concat ( swalClasses [ 'timer-progress-bar' ] , "\"></div>\n </div>\n </div>\n" ) . replace ( /(^|\n)\s*/g , '' ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const resetOldContainer = ( ) => {
const oldContainer = getContainer ( ) ;
2020-04-01 22:52:43 +00:00
if ( ! oldContainer ) {
return false ;
}
2022-02-07 20:05:14 +00:00
oldContainer . remove ( ) ;
2020-04-01 22:52:43 +00:00
removeClass ( [ document . documentElement , document . body ] , [ swalClasses [ 'no-backdrop' ] , swalClasses [ 'toast-shown' ] , swalClasses [ 'has-column' ] ] ) ;
return true ;
} ;
2022-02-07 20:05:14 +00:00
const resetValidationMessage = ( ) => {
globalState . currentInstance . resetValidationMessage ( ) ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
const addInputChangeListeners = ( ) => {
const popup = getPopup ( ) ;
const input = getDirectChildByClass ( popup , swalClasses . input ) ;
const file = getDirectChildByClass ( popup , swalClasses . file ) ;
const range = popup . querySelector ( "." . concat ( swalClasses . range , " input" ) ) ;
const rangeOutput = popup . querySelector ( "." . concat ( swalClasses . range , " output" ) ) ;
const select = getDirectChildByClass ( popup , swalClasses . select ) ;
const checkbox = popup . querySelector ( "." . concat ( swalClasses . checkbox , " input" ) ) ;
const textarea = getDirectChildByClass ( popup , swalClasses . textarea ) ;
2020-04-01 22:52:43 +00:00
input . oninput = resetValidationMessage ;
file . onchange = resetValidationMessage ;
select . onchange = resetValidationMessage ;
checkbox . onchange = resetValidationMessage ;
textarea . oninput = resetValidationMessage ;
2022-02-07 20:05:14 +00:00
range . oninput = ( ) => {
resetValidationMessage ( ) ;
2020-04-01 22:52:43 +00:00
rangeOutput . value = range . value ;
2019-06-16 09:20:59 +00:00
} ;
2022-02-07 20:05:14 +00:00
range . onchange = ( ) => {
resetValidationMessage ( ) ;
2020-04-01 22:52:43 +00:00
range . nextSibling . value = range . value ;
} ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const getTarget = target => typeof target === 'string' ? document . querySelector ( target ) : target ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const setupAccessibility = params => {
const popup = getPopup ( ) ;
2020-04-01 22:52:43 +00:00
popup . setAttribute ( 'role' , params . toast ? 'alert' : 'dialog' ) ;
popup . setAttribute ( 'aria-live' , params . toast ? 'polite' : 'assertive' ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( ! params . toast ) {
popup . setAttribute ( 'aria-modal' , 'true' ) ;
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const setupRTL = targetElement => {
2020-04-01 22:52:43 +00:00
if ( window . getComputedStyle ( targetElement ) . direction === 'rtl' ) {
addClass ( getContainer ( ) , swalClasses . rtl ) ;
}
} ;
/ *
* Add modal + backdrop to DOM
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const init = params => {
2020-04-01 22:52:43 +00:00
// Clean up the old popup container if it exists
2022-02-07 20:05:14 +00:00
const oldContainerExisted = resetOldContainer ( ) ;
2020-04-01 22:52:43 +00:00
/* istanbul ignore if */
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( isNodeEnv ( ) ) {
error ( 'SweetAlert2 requires document to initialize' ) ;
return ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const container = document . createElement ( 'div' ) ;
2020-04-01 22:52:43 +00:00
container . className = swalClasses . container ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( oldContainerExisted ) {
addClass ( container , swalClasses [ 'no-transition' ] ) ;
}
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
setInnerHtml ( container , sweetHTML ) ;
2022-02-07 20:05:14 +00:00
const targetElement = getTarget ( params . target ) ;
2020-04-01 22:52:43 +00:00
targetElement . appendChild ( container ) ;
setupAccessibility ( params ) ;
setupRTL ( targetElement ) ;
addInputChangeListeners ( ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
/ * *
* @ param { HTMLElement | object | string } param
* @ param { HTMLElement } target
* /
const parseHtmlToContainer = ( param , target ) => {
2020-04-01 22:52:43 +00:00
// DOM element
if ( param instanceof HTMLElement ) {
2022-02-07 20:05:14 +00:00
target . appendChild ( param ) ;
} // Object
else if ( typeof param === 'object' ) {
handleObject ( param , target ) ;
} // Plain string
else if ( param ) {
2020-04-01 22:52:43 +00:00
setInnerHtml ( target , param ) ;
}
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { object } param
* @ param { HTMLElement } target
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const handleObject = ( param , target ) => {
2020-04-01 22:52:43 +00:00
// JQuery element(s)
if ( param . jquery ) {
2022-02-07 20:05:14 +00:00
handleJqueryElem ( target , param ) ;
} // For other objects use their string representation
else {
2020-04-01 22:52:43 +00:00
setInnerHtml ( target , param . toString ( ) ) ;
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const handleJqueryElem = ( target , elem ) => {
2020-04-01 22:52:43 +00:00
target . textContent = '' ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( 0 in elem ) {
2022-02-07 20:05:14 +00:00
for ( let i = 0 ; ( i in elem ) ; i ++ ) {
2020-04-01 22:52:43 +00:00
target . appendChild ( elem [ i ] . cloneNode ( true ) ) ;
}
} else {
target . appendChild ( elem . cloneNode ( true ) ) ;
}
} ;
2022-02-07 20:05:14 +00:00
const animationEndEvent = ( ( ) => {
2020-04-01 22:52:43 +00:00
// Prevent run in Node env
2019-09-20 10:13:00 +00:00
2020-04-01 22:52:43 +00:00
/* istanbul ignore if */
if ( isNodeEnv ( ) ) {
return false ;
2019-06-16 09:20:59 +00:00
}
2019-09-20 10:13:00 +00:00
2022-02-07 20:05:14 +00:00
const testEl = document . createElement ( 'div' ) ;
const transEndEventNames = {
2020-04-01 22:52:43 +00:00
WebkitAnimation : 'webkitAnimationEnd' ,
2022-02-07 20:05:14 +00:00
// Chrome, Safari and Opera
animation : 'animationend' // Standard syntax
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
for ( const i in transEndEventNames ) {
2020-04-01 22:52:43 +00:00
if ( Object . prototype . hasOwnProperty . call ( transEndEventNames , i ) && typeof testEl . style [ i ] !== 'undefined' ) {
return transEndEventNames [ i ] ;
}
2019-09-20 10:13:00 +00:00
}
2020-04-01 22:52:43 +00:00
return false ;
2022-02-07 20:05:14 +00:00
} ) ( ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
// https://github.com/twbs/bootstrap/blob/master/js/src/modal.js
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const measureScrollbar = ( ) => {
const scrollDiv = document . createElement ( 'div' ) ;
2020-04-01 22:52:43 +00:00
scrollDiv . className = swalClasses [ 'scrollbar-measure' ] ;
document . body . appendChild ( scrollDiv ) ;
2022-02-07 20:05:14 +00:00
const scrollbarWidth = scrollDiv . getBoundingClientRect ( ) . width - scrollDiv . clientWidth ;
2020-04-01 22:52:43 +00:00
document . body . removeChild ( scrollDiv ) ;
return scrollbarWidth ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const renderActions = ( instance , params ) => {
const actions = getActions ( ) ;
const loader = getLoader ( ) ; // Actions (buttons) wrapper
2019-06-16 09:20:59 +00:00
2020-11-24 07:16:03 +00:00
if ( ! params . showConfirmButton && ! params . showDenyButton && ! params . showCancelButton ) {
2020-04-01 22:52:43 +00:00
hide ( actions ) ;
2022-02-07 20:05:14 +00:00
} else {
show ( actions ) ;
2020-04-01 22:52:43 +00:00
} // Custom class
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
applyCustomClass ( actions , params , 'actions' ) ; // Render all the buttons
renderButtons ( actions , loader , params ) ; // Loader
setInnerHtml ( loader , params . loaderHtml ) ;
applyCustomClass ( loader , params , 'loader' ) ;
} ;
function renderButtons ( actions , loader , params ) {
const confirmButton = getConfirmButton ( ) ;
const denyButton = getDenyButton ( ) ;
const cancelButton = getCancelButton ( ) ; // Render buttons
2019-06-16 09:20:59 +00:00
2020-11-24 07:16:03 +00:00
renderButton ( confirmButton , 'confirm' , params ) ;
renderButton ( denyButton , 'deny' , params ) ;
2020-11-25 09:31:52 +00:00
renderButton ( cancelButton , 'cancel' , params ) ;
handleButtonsStyling ( confirmButton , denyButton , cancelButton , params ) ;
2020-04-01 22:52:43 +00:00
if ( params . reverseButtons ) {
2022-02-07 20:05:14 +00:00
if ( params . toast ) {
actions . insertBefore ( cancelButton , confirmButton ) ;
actions . insertBefore ( denyButton , confirmButton ) ;
} else {
actions . insertBefore ( cancelButton , loader ) ;
actions . insertBefore ( denyButton , loader ) ;
actions . insertBefore ( confirmButton , loader ) ;
}
}
}
2019-06-16 09:20:59 +00:00
2020-11-24 07:16:03 +00:00
function handleButtonsStyling ( confirmButton , denyButton , cancelButton , params ) {
2020-11-25 09:31:52 +00:00
if ( ! params . buttonsStyling ) {
return removeClass ( [ confirmButton , denyButton , cancelButton ] , swalClasses . styled ) ;
}
2020-11-24 07:16:03 +00:00
addClass ( [ confirmButton , denyButton , cancelButton ] , swalClasses . styled ) ; // Buttons background colors
2020-04-01 22:52:43 +00:00
if ( params . confirmButtonColor ) {
confirmButton . style . backgroundColor = params . confirmButtonColor ;
2022-02-07 20:05:14 +00:00
addClass ( confirmButton , swalClasses [ 'default-outline' ] ) ;
2020-04-01 22:52:43 +00:00
}
2020-11-24 07:16:03 +00:00
if ( params . denyButtonColor ) {
denyButton . style . backgroundColor = params . denyButtonColor ;
2022-02-07 20:05:14 +00:00
addClass ( denyButton , swalClasses [ 'default-outline' ] ) ;
2020-11-24 07:16:03 +00:00
}
2020-04-01 22:52:43 +00:00
if ( params . cancelButtonColor ) {
cancelButton . style . backgroundColor = params . cancelButtonColor ;
2022-02-07 20:05:14 +00:00
addClass ( cancelButton , swalClasses [ 'default-outline' ] ) ;
2020-06-01 11:05:25 +00:00
}
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
function renderButton ( button , buttonType , params ) {
toggle ( button , params [ "show" . concat ( capitalizeFirstLetter ( buttonType ) , "Button" ) ] , 'inline-block' ) ;
setInnerHtml ( button , params [ "" . concat ( buttonType , "ButtonText" ) ] ) ; // Set caption text
button . setAttribute ( 'aria-label' , params [ "" . concat ( buttonType , "ButtonAriaLabel" ) ] ) ; // ARIA label
// Add buttons custom classes
button . className = swalClasses [ buttonType ] ;
applyCustomClass ( button , params , "" . concat ( buttonType , "Button" ) ) ;
addClass ( button , params [ "" . concat ( buttonType , "ButtonClass" ) ] ) ;
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
function handleBackdropParam ( container , backdrop ) {
if ( typeof backdrop === 'string' ) {
container . style . background = backdrop ;
} else if ( ! backdrop ) {
addClass ( [ document . documentElement , document . body ] , swalClasses [ 'no-backdrop' ] ) ;
}
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
function handlePositionParam ( container , position ) {
if ( position in swalClasses ) {
addClass ( container , swalClasses [ position ] ) ;
} else {
warn ( 'The "position" parameter is not valid, defaulting to "center"' ) ;
addClass ( container , swalClasses . center ) ;
}
}
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
function handleGrowParam ( container , grow ) {
if ( grow && typeof grow === 'string' ) {
2022-02-07 20:05:14 +00:00
const growClass = "grow-" . concat ( grow ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( growClass in swalClasses ) {
addClass ( container , swalClasses [ growClass ] ) ;
}
}
2019-06-16 09:20:59 +00:00
}
2022-02-07 20:05:14 +00:00
const renderContainer = ( instance , params ) => {
const container = getContainer ( ) ;
2020-04-01 22:52:43 +00:00
if ( ! container ) {
return ;
}
handleBackdropParam ( container , params . backdrop ) ;
handlePositionParam ( container , params . position ) ;
handleGrowParam ( container , params . grow ) ; // Custom class
2022-02-07 20:05:14 +00:00
applyCustomClass ( container , params , 'container' ) ;
2020-04-01 22:52:43 +00:00
} ;
/ * *
2022-02-07 20:05:14 +00:00
* This module contains ` WeakMap ` s for each effectively - "private property" that a ` Swal ` has .
2020-04-01 22:52:43 +00:00
* For example , to set the private property "foo" of ` this ` to "bar" , you can ` privateProps.foo.set(this, 'bar') `
* This is the approach that Babel will probably take to implement private methods / fields
* https : //github.com/tc39/proposal-private-methods
* https : //github.com/babel/babel/pull/7555
* Once we have the changes from that PR in Babel , and our core class fits reasonable in * one module *
* then we can use that language feature .
* /
var privateProps = {
2022-02-07 20:05:14 +00:00
awaitingPromise : new WeakMap ( ) ,
2020-04-01 22:52:43 +00:00
promise : new WeakMap ( ) ,
innerParams : new WeakMap ( ) ,
domCache : new WeakMap ( )
} ;
2022-02-07 20:05:14 +00:00
const inputTypes = [ 'input' , 'file' , 'range' , 'select' , 'radio' , 'checkbox' , 'textarea' ] ;
const renderInput = ( instance , params ) => {
const popup = getPopup ( ) ;
const innerParams = privateProps . innerParams . get ( instance ) ;
const rerender = ! innerParams || params . input !== innerParams . input ;
inputTypes . forEach ( inputType => {
const inputClass = swalClasses [ inputType ] ;
const inputContainer = getDirectChildByClass ( popup , inputClass ) ; // set attributes
2020-04-01 22:52:43 +00:00
setAttributes ( inputType , params . inputAttributes ) ; // set class
inputContainer . className = inputClass ;
if ( rerender ) {
hide ( inputContainer ) ;
}
} ) ;
if ( params . input ) {
if ( rerender ) {
showInput ( params ) ;
} // set custom class
setCustomClass ( params ) ;
}
} ;
2022-02-07 20:05:14 +00:00
const showInput = params => {
2020-04-01 22:52:43 +00:00
if ( ! renderInputType [ params . input ] ) {
return error ( "Unexpected type of input! Expected \"text\", \"email\", \"password\", \"number\", \"tel\", \"select\", \"radio\", \"checkbox\", \"textarea\", \"file\" or \"url\", got \"" . concat ( params . input , "\"" ) ) ;
}
2022-02-07 20:05:14 +00:00
const inputContainer = getInputContainer ( params . input ) ;
const input = renderInputType [ params . input ] ( inputContainer , params ) ;
2020-04-01 22:52:43 +00:00
show ( input ) ; // input autofocus
2022-02-07 20:05:14 +00:00
setTimeout ( ( ) => {
2020-04-01 22:52:43 +00:00
focusInput ( input ) ;
} ) ;
} ;
2022-02-07 20:05:14 +00:00
const removeAttributes = input => {
for ( let i = 0 ; i < input . attributes . length ; i ++ ) {
const attrName = input . attributes [ i ] . name ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
if ( ! [ 'type' , 'value' , 'style' ] . includes ( attrName ) ) {
2020-04-01 22:52:43 +00:00
input . removeAttribute ( attrName ) ;
}
}
} ;
2022-02-07 20:05:14 +00:00
const setAttributes = ( inputType , inputAttributes ) => {
const input = getInput ( getPopup ( ) , inputType ) ;
2020-04-01 22:52:43 +00:00
if ( ! input ) {
return ;
}
removeAttributes ( input ) ;
2022-02-07 20:05:14 +00:00
for ( const attr in inputAttributes ) {
2020-04-01 22:52:43 +00:00
input . setAttribute ( attr , inputAttributes [ attr ] ) ;
}
} ;
2022-02-07 20:05:14 +00:00
const setCustomClass = params => {
const inputContainer = getInputContainer ( params . input ) ;
2020-04-01 22:52:43 +00:00
if ( params . customClass ) {
addClass ( inputContainer , params . customClass . input ) ;
}
} ;
2022-02-07 20:05:14 +00:00
const setInputPlaceholder = ( input , params ) => {
2020-04-01 22:52:43 +00:00
if ( ! input . placeholder || params . inputPlaceholder ) {
input . placeholder = params . inputPlaceholder ;
}
} ;
2022-02-07 20:05:14 +00:00
const setInputLabel = ( input , prependTo , params ) => {
2020-11-25 09:31:52 +00:00
if ( params . inputLabel ) {
input . id = swalClasses . input ;
2022-02-07 20:05:14 +00:00
const label = document . createElement ( 'label' ) ;
const labelClass = swalClasses [ 'input-label' ] ;
2020-11-25 09:31:52 +00:00
label . setAttribute ( 'for' , input . id ) ;
label . className = labelClass ;
2021-01-11 13:35:52 +00:00
addClass ( label , params . customClass . inputLabel ) ;
2020-11-25 09:31:52 +00:00
label . innerText = params . inputLabel ;
prependTo . insertAdjacentElement ( 'beforebegin' , label ) ;
}
} ;
2022-02-07 20:05:14 +00:00
const getInputContainer = inputType => {
const inputClass = swalClasses [ inputType ] ? swalClasses [ inputType ] : swalClasses . input ;
return getDirectChildByClass ( getPopup ( ) , inputClass ) ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
const renderInputType = { } ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
renderInputType . text = renderInputType . email = renderInputType . password = renderInputType . number = renderInputType . tel = renderInputType . url = ( input , params ) => {
2020-04-01 22:52:43 +00:00
if ( typeof params . inputValue === 'string' || typeof params . inputValue === 'number' ) {
input . value = params . inputValue ;
} else if ( ! isPromise ( params . inputValue ) ) {
2022-02-07 20:05:14 +00:00
warn ( "Unexpected type of inputValue! Expected \"string\", \"number\" or \"Promise\", got \"" . concat ( typeof params . inputValue , "\"" ) ) ;
2020-04-01 22:52:43 +00:00
}
2020-11-25 09:31:52 +00:00
setInputLabel ( input , input , params ) ;
2020-04-01 22:52:43 +00:00
setInputPlaceholder ( input , params ) ;
input . type = params . input ;
return input ;
} ;
2022-02-07 20:05:14 +00:00
renderInputType . file = ( input , params ) => {
2020-11-25 09:31:52 +00:00
setInputLabel ( input , input , params ) ;
2020-04-01 22:52:43 +00:00
setInputPlaceholder ( input , params ) ;
return input ;
} ;
2022-02-07 20:05:14 +00:00
renderInputType . range = ( range , params ) => {
const rangeInput = range . querySelector ( 'input' ) ;
const rangeOutput = range . querySelector ( 'output' ) ;
2020-04-01 22:52:43 +00:00
rangeInput . value = params . inputValue ;
rangeInput . type = params . input ;
rangeOutput . value = params . inputValue ;
2020-11-25 09:31:52 +00:00
setInputLabel ( rangeInput , range , params ) ;
2020-04-01 22:52:43 +00:00
return range ;
} ;
2022-02-07 20:05:14 +00:00
renderInputType . select = ( select , params ) => {
2020-04-01 22:52:43 +00:00
select . textContent = '' ;
if ( params . inputPlaceholder ) {
2022-02-07 20:05:14 +00:00
const placeholder = document . createElement ( 'option' ) ;
2020-04-01 22:52:43 +00:00
setInnerHtml ( placeholder , params . inputPlaceholder ) ;
placeholder . value = '' ;
placeholder . disabled = true ;
placeholder . selected = true ;
select . appendChild ( placeholder ) ;
}
2020-11-25 09:31:52 +00:00
setInputLabel ( select , select , params ) ;
2020-04-01 22:52:43 +00:00
return select ;
} ;
2022-02-07 20:05:14 +00:00
renderInputType . radio = radio => {
2020-04-01 22:52:43 +00:00
radio . textContent = '' ;
return radio ;
} ;
2022-02-07 20:05:14 +00:00
renderInputType . checkbox = ( checkboxContainer , params ) => {
/** @type {HTMLInputElement} */
const checkbox = getInput ( getPopup ( ) , 'checkbox' ) ;
checkbox . value = '1' ;
2020-04-01 22:52:43 +00:00
checkbox . id = swalClasses . checkbox ;
checkbox . checked = Boolean ( params . inputValue ) ;
2022-02-07 20:05:14 +00:00
const label = checkboxContainer . querySelector ( 'span' ) ;
2020-04-01 22:52:43 +00:00
setInnerHtml ( label , params . inputPlaceholder ) ;
return checkboxContainer ;
} ;
2022-02-07 20:05:14 +00:00
renderInputType . textarea = ( textarea , params ) => {
2020-04-01 22:52:43 +00:00
textarea . value = params . inputValue ;
setInputPlaceholder ( textarea , params ) ;
2020-11-25 09:31:52 +00:00
setInputLabel ( textarea , textarea , params ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const getMargin = el => parseInt ( window . getComputedStyle ( el ) . marginLeft ) + parseInt ( window . getComputedStyle ( el ) . marginRight ) ; // https://github.com/sweetalert2/sweetalert2/issues/2291
2020-12-23 07:17:49 +00:00
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
setTimeout ( ( ) => {
// https://github.com/sweetalert2/sweetalert2/issues/1699
if ( 'MutationObserver' in window ) {
const initialPopupWidth = parseInt ( window . getComputedStyle ( getPopup ( ) ) . width ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const textareaResizeHandler = ( ) => {
const textareaWidth = textarea . offsetWidth + getMargin ( textarea ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
if ( textareaWidth > initialPopupWidth ) {
getPopup ( ) . style . width = "" . concat ( textareaWidth , "px" ) ;
} else {
getPopup ( ) . style . width = null ;
}
} ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
new MutationObserver ( textareaResizeHandler ) . observe ( textarea , {
attributes : true ,
attributeFilter : [ 'style' ]
} ) ;
}
} ) ;
2020-04-01 22:52:43 +00:00
return textarea ;
} ;
2022-02-07 20:05:14 +00:00
const renderContent = ( instance , params ) => {
const htmlContainer = getHtmlContainer ( ) ;
2021-02-23 11:22:20 +00:00
applyCustomClass ( htmlContainer , params , 'htmlContainer' ) ; // Content as HTML
2020-04-01 22:52:43 +00:00
if ( params . html ) {
2021-02-23 11:22:20 +00:00
parseHtmlToContainer ( params . html , htmlContainer ) ;
2022-02-07 20:05:14 +00:00
show ( htmlContainer , 'block' ) ;
} // Content as plain text
else if ( params . text ) {
2021-02-23 11:22:20 +00:00
htmlContainer . textContent = params . text ;
2022-02-07 20:05:14 +00:00
show ( htmlContainer , 'block' ) ;
} // No content
else {
2021-02-23 11:22:20 +00:00
hide ( htmlContainer ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
renderInput ( instance , params ) ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const renderFooter = ( instance , params ) => {
const footer = getFooter ( ) ;
2020-04-01 22:52:43 +00:00
toggle ( footer , params . footer ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( params . footer ) {
parseHtmlToContainer ( params . footer , footer ) ;
} // Custom class
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
applyCustomClass ( footer , params , 'footer' ) ;
2019-06-16 09:20:59 +00:00
} ;
2022-02-07 20:05:14 +00:00
const renderCloseButton = ( instance , params ) => {
const closeButton = getCloseButton ( ) ;
2020-04-01 22:52:43 +00:00
setInnerHtml ( closeButton , params . closeButtonHtml ) ; // Custom class
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
applyCustomClass ( closeButton , params , 'closeButton' ) ;
toggle ( closeButton , params . showCloseButton ) ;
closeButton . setAttribute ( 'aria-label' , params . closeButtonAriaLabel ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const renderIcon = ( instance , params ) => {
const innerParams = privateProps . innerParams . get ( instance ) ;
const icon = getIcon ( ) ; // if the given icon already rendered, apply the styling without re-rendering the icon
2019-06-16 09:20:59 +00:00
2021-02-23 11:22:20 +00:00
if ( innerParams && params . icon === innerParams . icon ) {
// Custom or default content
setContent ( icon , params ) ;
applyStyles ( icon , params ) ;
2020-04-01 22:52:43 +00:00
return ;
}
2019-06-16 09:20:59 +00:00
2021-02-23 11:22:20 +00:00
if ( ! params . icon && ! params . iconHtml ) {
return hide ( icon ) ;
2020-04-01 22:52:43 +00:00
}
2019-08-20 08:54:48 +00:00
2021-02-23 11:22:20 +00:00
if ( params . icon && Object . keys ( iconTypes ) . indexOf ( params . icon ) === - 1 ) {
2020-04-01 22:52:43 +00:00
error ( "Unknown icon! Expected \"success\", \"error\", \"warning\", \"info\" or \"question\", got \"" . concat ( params . icon , "\"" ) ) ;
2021-02-23 11:22:20 +00:00
return hide ( icon ) ;
2020-04-01 22:52:43 +00:00
}
2019-08-20 08:54:48 +00:00
2021-02-23 11:22:20 +00:00
show ( icon ) ; // Custom or default content
2019-08-20 08:54:48 +00:00
2021-02-23 11:22:20 +00:00
setContent ( icon , params ) ;
applyStyles ( icon , params ) ; // Animate icon
addClass ( icon , params . showClass . icon ) ;
2020-11-24 07:16:03 +00:00
} ;
2022-02-07 20:05:14 +00:00
const applyStyles = ( icon , params ) => {
for ( const iconType in iconTypes ) {
2021-02-23 11:22:20 +00:00
if ( params . icon !== iconType ) {
removeClass ( icon , iconTypes [ iconType ] ) ;
}
}
addClass ( icon , iconTypes [ params . icon ] ) ; // Icon color
2020-11-24 07:16:03 +00:00
setColor ( icon , params ) ; // Success icon background color
2022-02-07 20:05:14 +00:00
adjustSuccessIconBackgroundColor ( ) ; // Custom class
2020-11-24 07:16:03 +00:00
applyCustomClass ( icon , params , 'icon' ) ;
2020-04-01 22:52:43 +00:00
} ; // Adjust success icon background color to match the popup background color
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
const adjustSuccessIconBackgroundColor = ( ) => {
const popup = getPopup ( ) ;
const popupBackgroundColor = window . getComputedStyle ( popup ) . getPropertyValue ( 'background-color' ) ;
const successIconParts = popup . querySelectorAll ( '[class^=swal2-success-circular-line], .swal2-success-fix' ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
for ( let i = 0 ; i < successIconParts . length ; i ++ ) {
2020-04-01 22:52:43 +00:00
successIconParts [ i ] . style . backgroundColor = popupBackgroundColor ;
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const successIconHtml = "\n <div class=\"swal2-success-circular-line-left\"></div>\n <span class=\"swal2-success-line-tip\"></span> <span class=\"swal2-success-line-long\"></span>\n <div class=\"swal2-success-ring\"></div> <div class=\"swal2-success-fix\"></div>\n <div class=\"swal2-success-circular-line-right\"></div>\n" ;
const errorIconHtml = "\n <span class=\"swal2-x-mark\">\n <span class=\"swal2-x-mark-line-left\"></span>\n <span class=\"swal2-x-mark-line-right\"></span>\n </span>\n" ;
const setContent = ( icon , params ) => {
2020-04-01 22:52:43 +00:00
icon . textContent = '' ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( params . iconHtml ) {
setInnerHtml ( icon , iconContent ( params . iconHtml ) ) ;
} else if ( params . icon === 'success' ) {
2022-02-07 20:05:14 +00:00
setInnerHtml ( icon , successIconHtml ) ;
2020-04-01 22:52:43 +00:00
} else if ( params . icon === 'error' ) {
2022-02-07 20:05:14 +00:00
setInnerHtml ( icon , errorIconHtml ) ;
2020-04-01 22:52:43 +00:00
} else {
2022-02-07 20:05:14 +00:00
const defaultIconHtml = {
2020-04-01 22:52:43 +00:00
question : '?' ,
warning : '!' ,
info : 'i'
} ;
setInnerHtml ( icon , iconContent ( defaultIconHtml [ params . icon ] ) ) ;
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const setColor = ( icon , params ) => {
2020-11-24 07:16:03 +00:00
if ( ! params . iconColor ) {
return ;
}
icon . style . color = params . iconColor ;
icon . style . borderColor = params . iconColor ;
2022-02-07 20:05:14 +00:00
for ( const sel of [ '.swal2-success-line-tip' , '.swal2-success-line-long' , '.swal2-x-mark-line-left' , '.swal2-x-mark-line-right' ] ) {
2020-11-24 07:16:03 +00:00
setStyle ( icon , sel , 'backgroundColor' , params . iconColor ) ;
}
setStyle ( icon , '.swal2-success-ring' , 'borderColor' , params . iconColor ) ;
} ;
2022-02-07 20:05:14 +00:00
const iconContent = content => "<div class=\"" . concat ( swalClasses [ 'icon-content' ] , "\">" ) . concat ( content , "</div>" ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const renderImage = ( instance , params ) => {
const image = getImage ( ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( ! params . imageUrl ) {
return hide ( image ) ;
}
2019-06-16 09:20:59 +00:00
2020-06-01 11:05:25 +00:00
show ( image , '' ) ; // Src, alt
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
image . setAttribute ( 'src' , params . imageUrl ) ;
image . setAttribute ( 'alt' , params . imageAlt ) ; // Width, height
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
applyNumericalStyle ( image , 'width' , params . imageWidth ) ;
applyNumericalStyle ( image , 'height' , params . imageHeight ) ; // Class
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
image . className = swalClasses . image ;
applyCustomClass ( image , params , 'image' ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const createStepElement = step => {
const stepEl = document . createElement ( 'li' ) ;
2020-04-01 22:52:43 +00:00
addClass ( stepEl , swalClasses [ 'progress-step' ] ) ;
setInnerHtml ( stepEl , step ) ;
return stepEl ;
} ;
2019-10-21 09:54:16 +00:00
2022-02-07 20:05:14 +00:00
const createLineElement = params => {
const lineEl = document . createElement ( 'li' ) ;
2020-04-01 22:52:43 +00:00
addClass ( lineEl , swalClasses [ 'progress-step-line' ] ) ;
2019-10-21 09:54:16 +00:00
2020-04-01 22:52:43 +00:00
if ( params . progressStepsDistance ) {
lineEl . style . width = params . progressStepsDistance ;
}
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
return lineEl ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const renderProgressSteps = ( instance , params ) => {
const progressStepsContainer = getProgressSteps ( ) ;
2019-08-20 08:54:48 +00:00
2020-04-01 22:52:43 +00:00
if ( ! params . progressSteps || params . progressSteps . length === 0 ) {
return hide ( progressStepsContainer ) ;
}
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
show ( progressStepsContainer ) ;
progressStepsContainer . textContent = '' ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( params . currentProgressStep >= params . progressSteps . length ) {
2020-04-01 22:52:43 +00:00
warn ( 'Invalid currentProgressStep parameter, it should be less than progressSteps.length ' + '(currentProgressStep like JS arrays starts from 0)' ) ;
2019-06-16 09:20:59 +00:00
}
2022-02-07 20:05:14 +00:00
params . progressSteps . forEach ( ( step , index ) => {
const stepEl = createStepElement ( step ) ;
2020-04-01 22:52:43 +00:00
progressStepsContainer . appendChild ( stepEl ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( index === params . currentProgressStep ) {
2020-04-01 22:52:43 +00:00
addClass ( stepEl , swalClasses [ 'active-progress-step' ] ) ;
}
if ( index !== params . progressSteps . length - 1 ) {
2022-02-07 20:05:14 +00:00
const lineEl = createLineElement ( params ) ;
2020-04-01 22:52:43 +00:00
progressStepsContainer . appendChild ( lineEl ) ;
}
} ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const renderTitle = ( instance , params ) => {
const title = getTitle ( ) ;
2021-09-17 19:28:20 +00:00
toggle ( title , params . title || params . titleText , 'block' ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( params . title ) {
parseHtmlToContainer ( params . title , title ) ;
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
if ( params . titleText ) {
title . innerText = params . titleText ;
} // Custom class
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
applyCustomClass ( title , params , 'title' ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const renderPopup = ( instance , params ) => {
const container = getContainer ( ) ;
const popup = getPopup ( ) ; // Width
// https://github.com/sweetalert2/sweetalert2/issues/2170
2019-08-20 08:54:48 +00:00
2021-02-23 11:22:20 +00:00
if ( params . toast ) {
applyNumericalStyle ( container , 'width' , params . width ) ;
popup . style . width = '100%' ;
2022-02-07 20:05:14 +00:00
popup . insertBefore ( getLoader ( ) , getIcon ( ) ) ;
2021-02-23 11:22:20 +00:00
} else {
applyNumericalStyle ( popup , 'width' , params . width ) ;
} // Padding
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
applyNumericalStyle ( popup , 'padding' , params . padding ) ; // Color
if ( params . color ) {
popup . style . color = params . color ;
} // Background
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( params . background ) {
popup . style . background = params . background ;
2021-03-20 20:39:14 +00:00
}
2019-06-16 09:20:59 +00:00
2021-03-20 20:39:14 +00:00
hide ( getValidationMessage ( ) ) ; // Classes
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
addClasses ( popup , params ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const addClasses = ( popup , params ) => {
2020-04-01 22:52:43 +00:00
// Default Class + showClass when updating Swal.update({})
popup . className = "" . concat ( swalClasses . popup , " " ) . concat ( isVisible ( popup ) ? params . showClass . popup : '' ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( params . toast ) {
addClass ( [ document . documentElement , document . body ] , swalClasses [ 'toast-shown' ] ) ;
addClass ( popup , swalClasses . toast ) ;
} else {
addClass ( popup , swalClasses . modal ) ;
} // Custom class
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
applyCustomClass ( popup , params , 'popup' ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( typeof params . customClass === 'string' ) {
addClass ( popup , params . customClass ) ;
} // Icon class (#1842)
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( params . icon ) {
addClass ( popup , swalClasses [ "icon-" . concat ( params . icon ) ] ) ;
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const render = ( instance , params ) => {
2020-04-01 22:52:43 +00:00
renderPopup ( instance , params ) ;
renderContainer ( instance , params ) ;
2022-02-07 20:05:14 +00:00
renderProgressSteps ( instance , params ) ;
renderIcon ( instance , params ) ;
renderImage ( instance , params ) ;
renderTitle ( instance , params ) ;
renderCloseButton ( instance , params ) ;
2020-04-01 22:52:43 +00:00
renderContent ( instance , params ) ;
renderActions ( instance , params ) ;
renderFooter ( instance , params ) ;
2019-06-16 09:20:59 +00:00
2020-11-24 07:16:03 +00:00
if ( typeof params . didRender === 'function' ) {
params . didRender ( getPopup ( ) ) ;
2020-04-01 22:52:43 +00:00
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const DismissReason = Object . freeze ( {
cancel : 'cancel' ,
backdrop : 'backdrop' ,
close : 'close' ,
esc : 'esc' ,
timer : 'timer'
} ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
// Adding aria-hidden="true" to elements outside of the active modal dialog ensures that
// elements not within the active modal dialog will not be surfaced if a user opens a screen
// reader’ s list of elements (headings, form controls, landmarks, etc.) in the document.
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const setAriaHidden = ( ) => {
const bodyChildren = toArray ( document . body . children ) ;
bodyChildren . forEach ( el => {
if ( el === getContainer ( ) || el . contains ( getContainer ( ) ) ) {
return ;
}
2020-11-24 07:16:03 +00:00
2022-02-07 20:05:14 +00:00
if ( el . hasAttribute ( 'aria-hidden' ) ) {
el . setAttribute ( 'data-previous-aria-hidden' , el . getAttribute ( 'aria-hidden' ) ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
el . setAttribute ( 'aria-hidden' , 'true' ) ;
} ) ;
} ;
const unsetAriaHidden = ( ) => {
const bodyChildren = toArray ( document . body . children ) ;
bodyChildren . forEach ( el => {
if ( el . hasAttribute ( 'data-previous-aria-hidden' ) ) {
el . setAttribute ( 'aria-hidden' , el . getAttribute ( 'data-previous-aria-hidden' ) ) ;
el . removeAttribute ( 'data-previous-aria-hidden' ) ;
} else {
el . removeAttribute ( 'aria-hidden' ) ;
}
} ) ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const swalStringParams = [ 'swal-title' , 'swal-html' , 'swal-footer' ] ;
const getTemplateParams = params => {
const template = typeof params . template === 'string' ? document . querySelector ( params . template ) : params . template ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( ! template ) {
return { } ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
/** @type {DocumentFragment} */
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const templateContent = template . content ;
showWarningsForElements ( templateContent ) ;
const result = Object . assign ( getSwalParams ( templateContent ) , getSwalButtons ( templateContent ) , getSwalImage ( templateContent ) , getSwalIcon ( templateContent ) , getSwalInput ( templateContent ) , getSwalStringParams ( templateContent , swalStringParams ) ) ;
return result ;
} ;
2020-04-01 22:52:43 +00:00
/ * *
2022-02-07 20:05:14 +00:00
* @ param { DocumentFragment } templateContent
2020-04-01 22:52:43 +00:00
* /
2022-02-07 20:05:14 +00:00
const getSwalParams = templateContent => {
const result = { } ;
toArray ( templateContent . querySelectorAll ( 'swal-param' ) ) . forEach ( param => {
showWarningsForAttributes ( param , [ 'name' , 'value' ] ) ;
const paramName = param . getAttribute ( 'name' ) ;
const value = param . getAttribute ( 'value' ) ;
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
if ( typeof defaultParams [ paramName ] === 'boolean' && value === 'false' ) {
result [ paramName ] = false ;
}
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
if ( typeof defaultParams [ paramName ] === 'object' ) {
result [ paramName ] = JSON . parse ( value ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
} ) ;
return result ;
} ;
/ * *
* @ param { DocumentFragment } templateContent
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const getSwalButtons = templateContent => {
const result = { } ;
toArray ( templateContent . querySelectorAll ( 'swal-button' ) ) . forEach ( button => {
showWarningsForAttributes ( button , [ 'type' , 'color' , 'aria-label' ] ) ;
const type = button . getAttribute ( 'type' ) ;
result [ "" . concat ( type , "ButtonText" ) ] = button . innerHTML ;
result [ "show" . concat ( capitalizeFirstLetter ( type ) , "Button" ) ] = true ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( button . hasAttribute ( 'color' ) ) {
result [ "" . concat ( type , "ButtonColor" ) ] = button . getAttribute ( 'color' ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( button . hasAttribute ( 'aria-label' ) ) {
result [ "" . concat ( type , "ButtonAriaLabel" ) ] = button . getAttribute ( 'aria-label' ) ;
}
} ) ;
return result ;
} ;
2020-04-01 22:52:43 +00:00
/ * *
2022-02-07 20:05:14 +00:00
* @ param { DocumentFragment } templateContent
2020-04-01 22:52:43 +00:00
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const getSwalImage = templateContent => {
const result = { } ;
/** @type {HTMLElement} */
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const image = templateContent . querySelector ( 'swal-image' ) ;
2020-11-25 09:31:52 +00:00
2022-02-07 20:05:14 +00:00
if ( image ) {
showWarningsForAttributes ( image , [ 'src' , 'width' , 'height' , 'alt' ] ) ;
2020-11-25 09:31:52 +00:00
2022-02-07 20:05:14 +00:00
if ( image . hasAttribute ( 'src' ) ) {
result . imageUrl = image . getAttribute ( 'src' ) ;
}
2020-11-25 09:31:52 +00:00
2022-02-07 20:05:14 +00:00
if ( image . hasAttribute ( 'width' ) ) {
result . imageWidth = image . getAttribute ( 'width' ) ;
}
if ( image . hasAttribute ( 'height' ) ) {
result . imageHeight = image . getAttribute ( 'height' ) ;
}
if ( image . hasAttribute ( 'alt' ) ) {
result . imageAlt = image . getAttribute ( 'alt' ) ;
}
2020-11-25 09:31:52 +00:00
}
2022-02-07 20:05:14 +00:00
return result ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { DocumentFragment } templateContent
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const getSwalIcon = templateContent => {
const result = { } ;
/** @type {HTMLElement} */
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const icon = templateContent . querySelector ( 'swal-icon' ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( icon ) {
showWarningsForAttributes ( icon , [ 'type' , 'color' ] ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( icon . hasAttribute ( 'type' ) ) {
result . icon = icon . getAttribute ( 'type' ) ;
2021-09-17 19:28:20 +00:00
}
2022-02-07 20:05:14 +00:00
if ( icon . hasAttribute ( 'color' ) ) {
result . iconColor = icon . getAttribute ( 'color' ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
result . iconHtml = icon . innerHTML ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
return result ;
2020-04-01 22:52:43 +00:00
} ;
/ * *
2022-02-07 20:05:14 +00:00
* @ param { DocumentFragment } templateContent
2020-04-01 22:52:43 +00:00
* /
2022-02-07 20:05:14 +00:00
const getSwalInput = templateContent => {
const result = { } ;
/** @type {HTMLElement} */
const input = templateContent . querySelector ( 'swal-input' ) ;
if ( input ) {
showWarningsForAttributes ( input , [ 'type' , 'label' , 'placeholder' , 'value' ] ) ;
result . input = input . getAttribute ( 'type' ) || 'text' ;
if ( input . hasAttribute ( 'label' ) ) {
result . inputLabel = input . getAttribute ( 'label' ) ;
}
if ( input . hasAttribute ( 'placeholder' ) ) {
result . inputPlaceholder = input . getAttribute ( 'placeholder' ) ;
}
if ( input . hasAttribute ( 'value' ) ) {
result . inputValue = input . getAttribute ( 'value' ) ;
}
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
const inputOptions = templateContent . querySelectorAll ( 'swal-input-option' ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
if ( inputOptions . length ) {
result . inputOptions = { } ;
toArray ( inputOptions ) . forEach ( option => {
showWarningsForAttributes ( option , [ 'value' ] ) ;
const optionValue = option . getAttribute ( 'value' ) ;
const optionName = option . innerHTML ;
result . inputOptions [ optionValue ] = optionName ;
} ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
return result ;
2020-04-01 22:52:43 +00:00
} ;
/ * *
2022-02-07 20:05:14 +00:00
* @ param { DocumentFragment } templateContent
* @ param { string [ ] } paramNames
2020-04-01 22:52:43 +00:00
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const getSwalStringParams = ( templateContent , paramNames ) => {
const result = { } ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
for ( const i in paramNames ) {
const paramName = paramNames [ i ] ;
/** @type {HTMLElement} */
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const tag = templateContent . querySelector ( paramName ) ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( tag ) {
showWarningsForAttributes ( tag , [ ] ) ;
result [ paramName . replace ( /^swal-/ , '' ) ] = tag . innerHTML . trim ( ) ;
2020-12-23 07:17:49 +00:00
}
}
2022-02-07 20:05:14 +00:00
return result ;
2020-04-01 22:52:43 +00:00
} ;
/ * *
2022-02-07 20:05:14 +00:00
* @ param { DocumentFragment } templateContent
2020-04-01 22:52:43 +00:00
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const showWarningsForElements = templateContent => {
const allowedElements = swalStringParams . concat ( [ 'swal-param' , 'swal-button' , 'swal-image' , 'swal-icon' , 'swal-input' , 'swal-input-option' ] ) ;
toArray ( templateContent . children ) . forEach ( el => {
const tagName = el . tagName . toLowerCase ( ) ;
if ( allowedElements . indexOf ( tagName ) === - 1 ) {
warn ( "Unrecognized element <" . concat ( tagName , ">" ) ) ;
}
} ) ;
2020-04-01 22:52:43 +00:00
} ;
/ * *
2022-02-07 20:05:14 +00:00
* @ param { HTMLElement } el
* @ param { string [ ] } allowedAttributes
2020-04-01 22:52:43 +00:00
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const showWarningsForAttributes = ( el , allowedAttributes ) => {
toArray ( el . attributes ) . forEach ( attribute => {
if ( allowedAttributes . indexOf ( attribute . name ) === - 1 ) {
warn ( [ "Unrecognized attribute \"" . concat ( attribute . name , "\" on <" ) . concat ( el . tagName . toLowerCase ( ) , ">." ) , "" . concat ( allowedAttributes . length ? "Allowed attributes are: " . concat ( allowedAttributes . join ( ', ' ) ) : 'To set the value, use HTML within the element.' ) ] ) ;
}
} ) ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
var defaultInputValidators = {
email : ( string , validationMessage ) => {
return /^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/ . test ( string ) ? Promise . resolve ( ) : Promise . resolve ( validationMessage || 'Invalid email address' ) ;
} ,
url : ( string , validationMessage ) => {
// taken from https://stackoverflow.com/a/3809435 with a small change from #1306 and #2013
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' ) ;
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
function setDefaultInputValidators ( params ) {
// Use default `inputValidator` for supported input types if not provided
if ( ! params . inputValidator ) {
Object . keys ( defaultInputValidators ) . forEach ( key => {
if ( params . input === key ) {
params . inputValidator = defaultInputValidators [ key ] ;
}
} ) ;
}
}
function validateCustomTargetElement ( params ) {
// Determine if the custom target element is valid
if ( ! params . target || typeof params . target === 'string' && ! document . querySelector ( params . target ) || typeof params . target !== 'string' && ! params . target . appendChild ) {
warn ( 'Target parameter is not valid, defaulting to "body"' ) ;
params . target = 'body' ;
}
}
/ * *
* Set type , text and actions on popup
*
2020-04-01 22:52:43 +00:00
* @ param params
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
function setParameters ( params ) {
setDefaultInputValidators ( params ) ; // showLoaderOnConfirm && preConfirm
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( params . showLoaderOnConfirm && ! params . preConfirm ) {
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' ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
validateCustomTargetElement ( params ) ; // Replace newlines with <br> in title
if ( typeof params . title === 'string' ) {
params . title = params . title . split ( '\n' ) . join ( '<br />' ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
init ( params ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
class Timer {
constructor ( callback , delay ) {
this . callback = callback ;
this . remaining = delay ;
this . running = false ;
this . start ( ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
start ( ) {
if ( ! this . running ) {
this . running = true ;
this . started = new Date ( ) ;
this . id = setTimeout ( this . callback , this . remaining ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
return this . remaining ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
stop ( ) {
if ( this . running ) {
this . running = false ;
clearTimeout ( this . id ) ;
this . remaining -= new Date ( ) . getTime ( ) - this . started . getTime ( ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
return this . remaining ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
increase ( n ) {
const running = this . running ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( running ) {
this . stop ( ) ;
}
this . remaining += n ;
if ( running ) {
this . start ( ) ;
}
return this . remaining ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
getTimerLeft ( ) {
if ( this . running ) {
this . stop ( ) ;
this . start ( ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
return this . remaining ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
isRunning ( ) {
return this . running ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const fixScrollbar = ( ) => {
2020-04-01 22:52:43 +00:00
// for queues, do not do this more than once
if ( states . previousBodyPadding !== null ) {
return ;
} // if the body has overflow
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( document . body . scrollHeight > window . innerHeight ) {
// add padding so the content doesn't shift after removal of scrollbar
states . previousBodyPadding = parseInt ( window . getComputedStyle ( document . body ) . getPropertyValue ( 'padding-right' ) ) ;
document . body . style . paddingRight = "" . concat ( states . previousBodyPadding + measureScrollbar ( ) , "px" ) ;
}
} ;
2022-02-07 20:05:14 +00:00
const undoScrollbar = ( ) => {
2020-04-01 22:52:43 +00:00
if ( states . previousBodyPadding !== null ) {
document . body . style . paddingRight = "" . concat ( states . previousBodyPadding , "px" ) ;
states . previousBodyPadding = null ;
}
} ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
/* istanbul ignore file */
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const iOSfix = ( ) => {
const iOS = // @ts-ignore
/iPad|iPhone|iPod/ . test ( navigator . userAgent ) && ! window . MSStream || navigator . platform === 'MacIntel' && navigator . maxTouchPoints > 1 ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( iOS && ! hasClass ( document . body , swalClasses . iosfix ) ) {
2022-02-07 20:05:14 +00:00
const offset = document . body . scrollTop ;
2020-04-01 22:52:43 +00:00
document . body . style . top = "" . concat ( offset * - 1 , "px" ) ;
addClass ( document . body , swalClasses . iosfix ) ;
lockBodyScroll ( ) ;
2022-02-07 20:05:14 +00:00
addBottomPaddingForTallPopups ( ) ;
2020-06-11 12:27:46 +00:00
}
} ;
2022-02-07 20:05:14 +00:00
/ * *
* https : //github.com/sweetalert2/sweetalert2/issues/1948
* /
2020-06-11 12:27:46 +00:00
2022-02-07 20:05:14 +00:00
const addBottomPaddingForTallPopups = ( ) => {
const ua = navigator . userAgent ;
const iOS = ! ! ua . match ( /iPad/i ) || ! ! ua . match ( /iPhone/i ) ;
const webkit = ! ! ua . match ( /WebKit/i ) ;
const iOSSafari = iOS && webkit && ! ua . match ( /CriOS/i ) ;
2020-06-11 12:27:46 +00:00
2022-02-07 20:05:14 +00:00
if ( iOSSafari ) {
const bottomPanelHeight = 44 ;
2020-06-11 12:27:46 +00:00
if ( getPopup ( ) . scrollHeight > window . innerHeight - bottomPanelHeight ) {
getContainer ( ) . style . paddingBottom = "" . concat ( bottomPanelHeight , "px" ) ;
}
2020-04-01 22:52:43 +00:00
}
} ;
2022-02-07 20:05:14 +00:00
/ * *
* https : //github.com/sweetalert2/sweetalert2/issues/1246
* /
2019-09-17 09:37:57 +00:00
2022-02-07 20:05:14 +00:00
const lockBodyScroll = ( ) => {
const container = getContainer ( ) ;
let preventTouchMove ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
container . ontouchstart = e => {
2020-11-25 09:31:52 +00:00
preventTouchMove = shouldPreventTouchMove ( e ) ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
container . ontouchmove = e => {
2020-04-01 22:52:43 +00:00
if ( preventTouchMove ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
} ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const shouldPreventTouchMove = event => {
const target = event . target ;
const container = getContainer ( ) ;
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
if ( isStylus ( event ) || isZoom ( event ) ) {
2020-11-25 09:31:52 +00:00
return false ;
}
2020-06-01 11:05:25 +00:00
if ( target === container ) {
return true ;
}
if ( ! isScrollable ( container ) && target . tagName !== 'INPUT' && // #1603
2022-02-07 20:05:14 +00:00
target . tagName !== 'TEXTAREA' && // #2266
! ( isScrollable ( getHtmlContainer ( ) ) && // #1944
getHtmlContainer ( ) . contains ( target ) ) ) {
2020-06-01 11:05:25 +00:00
return true ;
}
return false ;
} ;
2022-02-07 20:05:14 +00:00
/ * *
* https : //github.com/sweetalert2/sweetalert2/issues/1786
*
* @ param { * } event
* @ returns { boolean }
* /
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
const isStylus = event => {
2020-11-25 09:31:52 +00:00
return event . touches && event . touches . length && event . touches [ 0 ] . touchType === 'stylus' ;
} ;
2022-02-07 20:05:14 +00:00
/ * *
* https : //github.com/sweetalert2/sweetalert2/issues/1891
*
* @ param { TouchEvent } event
* @ returns { boolean }
* /
2020-11-25 09:31:52 +00:00
2022-02-07 20:05:14 +00:00
const isZoom = event => {
2020-11-25 09:31:52 +00:00
return event . touches && event . touches . length > 1 ;
} ;
2022-02-07 20:05:14 +00:00
const undoIOSfix = ( ) => {
2020-04-01 22:52:43 +00:00
if ( hasClass ( document . body , swalClasses . iosfix ) ) {
2022-02-07 20:05:14 +00:00
const offset = parseInt ( document . body . style . top , 10 ) ;
2020-04-01 22:52:43 +00:00
removeClass ( document . body , swalClasses . iosfix ) ;
document . body . style . top = '' ;
document . body . scrollTop = offset * - 1 ;
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const SHOW _CLASS _TIMEOUT = 10 ;
/ * *
* Open popup , add necessary classes and styles , fix scrollbar
*
* @ param params
* /
const openPopup = params => {
const container = getContainer ( ) ;
const popup = getPopup ( ) ;
if ( typeof params . willOpen === 'function' ) {
params . willOpen ( popup ) ;
}
const bodyStyles = window . getComputedStyle ( document . body ) ;
const initialBodyOverflow = bodyStyles . overflowY ;
addClasses$1 ( container , popup , params ) ; // scrolling is 'hidden' until animation is done, after that 'auto'
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
setTimeout ( ( ) => {
setScrollingVisibility ( container , popup ) ;
} , SHOW _CLASS _TIMEOUT ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( isModal ( ) ) {
fixScrollContainer ( container , params . scrollbarPadding , initialBodyOverflow ) ;
setAriaHidden ( ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( ! isToast ( ) && ! globalState . previousActiveElement ) {
globalState . previousActiveElement = document . activeElement ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( typeof params . didOpen === 'function' ) {
setTimeout ( ( ) => params . didOpen ( popup ) ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
removeClass ( container , swalClasses [ 'no-transition' ] ) ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const swalOpenAnimationFinished = event => {
const popup = getPopup ( ) ;
if ( event . target !== popup ) {
return ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
const container = getContainer ( ) ;
popup . removeEventListener ( animationEndEvent , swalOpenAnimationFinished ) ;
container . style . overflowY = 'auto' ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
const setScrollingVisibility = ( container , popup ) => {
if ( animationEndEvent && hasCssAnimation ( popup ) ) {
container . style . overflowY = 'hidden' ;
popup . addEventListener ( animationEndEvent , swalOpenAnimationFinished ) ;
} else {
container . style . overflowY = 'auto' ;
2020-04-01 22:52:43 +00:00
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const fixScrollContainer = ( container , scrollbarPadding , initialBodyOverflow ) => {
iOSfix ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( scrollbarPadding && initialBodyOverflow !== 'hidden' ) {
fixScrollbar ( ) ;
} // sweetalert2/issues/1247
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
setTimeout ( ( ) => {
container . scrollTop = 0 ;
2020-04-01 22:52:43 +00:00
} ) ;
} ;
2022-02-07 20:05:14 +00:00
const addClasses$1 = ( container , popup , params ) => {
addClass ( container , params . showClass . backdrop ) ; // this workaround with opacity is needed for https://github.com/sweetalert2/sweetalert2/issues/2059
popup . style . setProperty ( 'opacity' , '0' , 'important' ) ;
show ( popup , 'grid' ) ;
setTimeout ( ( ) => {
// Animate popup right after showing it
addClass ( popup , params . showClass . popup ) ; // and remove the opacity workaround
popup . style . removeProperty ( 'opacity' ) ;
} , SHOW _CLASS _TIMEOUT ) ; // 10ms in order to fix #2062
addClass ( [ document . documentElement , document . body ] , swalClasses . shown ) ;
if ( params . heightAuto && params . backdrop && ! params . toast ) {
addClass ( [ document . documentElement , document . body ] , swalClasses [ 'height-auto' ] ) ;
}
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
/ * *
2022-02-07 20:05:14 +00:00
* Shows loader ( spinner ) , this is useful with AJAX requests .
* By default the loader be shown instead of the "Confirm" button .
2020-04-01 22:52:43 +00:00
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const showLoading = buttonToReplace => {
let popup = getPopup ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( ! popup ) {
new Swal ( ) ; // eslint-disable-line no-new
2019-06-16 09:20:59 +00:00
}
2022-02-07 20:05:14 +00:00
popup = getPopup ( ) ;
const loader = getLoader ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( isToast ( ) ) {
hide ( getIcon ( ) ) ;
} else {
replaceButton ( popup , buttonToReplace ) ;
2020-04-01 22:52:43 +00:00
}
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
show ( loader ) ;
popup . setAttribute ( 'data-loading' , true ) ;
popup . setAttribute ( 'aria-busy' , true ) ;
popup . focus ( ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const replaceButton = ( popup , buttonToReplace ) => {
const actions = getActions ( ) ;
const loader = getLoader ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( ! buttonToReplace && isVisible ( getConfirmButton ( ) ) ) {
buttonToReplace = getConfirmButton ( ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
show ( actions ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( buttonToReplace ) {
hide ( buttonToReplace ) ;
loader . setAttribute ( 'data-button-to-replace' , buttonToReplace . className ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
loader . parentNode . insertBefore ( loader , buttonToReplace ) ;
addClass ( [ popup , actions ] , swalClasses . loading ) ;
} ;
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
const handleInputOptionsAndValue = ( instance , params ) => {
if ( params . input === 'select' || params . input === 'radio' ) {
handleInputOptions ( instance , params ) ;
} else if ( [ 'text' , 'email' , 'number' , 'tel' , 'textarea' ] . includes ( params . input ) && ( hasToPromiseFn ( params . inputValue ) || isPromise ( params . inputValue ) ) ) {
showLoading ( getConfirmButton ( ) ) ;
handleInputValue ( instance , params ) ;
2020-11-24 07:16:03 +00:00
}
} ;
2022-02-07 20:05:14 +00:00
const getInputValue = ( instance , innerParams ) => {
const input = instance . getInput ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( ! input ) {
return null ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
switch ( innerParams . input ) {
case 'checkbox' :
return getCheckboxValue ( input ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
case 'radio' :
return getRadioValue ( input ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
case 'file' :
return getFileValue ( input ) ;
2020-11-24 07:16:03 +00:00
2022-02-07 20:05:14 +00:00
default :
return innerParams . inputAutoTrim ? input . value . trim ( ) : input . value ;
}
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const getCheckboxValue = input => input . checked ? 1 : 0 ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const getRadioValue = input => input . checked ? input . value : null ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const getFileValue = input => input . files . length ? input . getAttribute ( 'multiple' ) !== null ? input . files : input . files [ 0 ] : null ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const handleInputOptions = ( instance , params ) => {
const popup = getPopup ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const processInputOptions = inputOptions => populateInputOptions [ params . input ] ( popup , formatInputOptions ( inputOptions ) , params ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( hasToPromiseFn ( params . inputOptions ) || isPromise ( params . inputOptions ) ) {
showLoading ( getConfirmButton ( ) ) ;
asPromise ( params . inputOptions ) . then ( inputOptions => {
instance . hideLoading ( ) ;
processInputOptions ( inputOptions ) ;
} ) ;
} else if ( typeof params . inputOptions === 'object' ) {
processInputOptions ( params . inputOptions ) ;
2020-04-01 22:52:43 +00:00
} else {
2022-02-07 20:05:14 +00:00
error ( "Unexpected type of inputOptions! Expected object, Map or Promise, got " . concat ( typeof params . inputOptions ) ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const handleInputValue = ( instance , params ) => {
const input = instance . getInput ( ) ;
hide ( input ) ;
asPromise ( params . inputValue ) . then ( inputValue => {
input . value = params . input === 'number' ? parseFloat ( inputValue ) || 0 : "" . concat ( inputValue ) ;
show ( input ) ;
input . focus ( ) ;
instance . hideLoading ( ) ;
} ) . catch ( err => {
error ( "Error in inputValue promise: " . concat ( err ) ) ;
input . value = '' ;
show ( input ) ;
input . focus ( ) ;
instance . hideLoading ( ) ;
} ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const populateInputOptions = {
select : ( popup , inputOptions , params ) => {
const select = getDirectChildByClass ( popup , swalClasses . select ) ;
2020-11-25 09:31:52 +00:00
2022-02-07 20:05:14 +00:00
const renderOption = ( parent , optionLabel , optionValue ) => {
const option = document . createElement ( 'option' ) ;
option . value = optionValue ;
setInnerHtml ( option , optionLabel ) ;
option . selected = isSelected ( optionValue , params . inputValue ) ;
parent . appendChild ( option ) ;
} ;
2020-11-25 09:31:52 +00:00
2022-02-07 20:05:14 +00:00
inputOptions . forEach ( inputOption => {
const optionValue = inputOption [ 0 ] ;
const optionLabel = inputOption [ 1 ] ; // <optgroup> spec:
// https://www.w3.org/TR/html401/interact/forms.html#h-17.6
// "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
// check whether this is a <optgroup>
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( Array . isArray ( optionLabel ) ) {
// if it is an array, then it is an <optgroup>
const optgroup = document . createElement ( 'optgroup' ) ;
optgroup . label = optionValue ;
optgroup . disabled = false ; // not configurable for now
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
select . appendChild ( optgroup ) ;
optionLabel . forEach ( o => renderOption ( optgroup , o [ 1 ] , o [ 0 ] ) ) ;
} else {
// case of <option>
renderOption ( select , optionLabel , optionValue ) ;
}
} ) ;
select . focus ( ) ;
} ,
radio : ( popup , inputOptions , params ) => {
const radio = getDirectChildByClass ( popup , swalClasses . radio ) ;
inputOptions . forEach ( inputOption => {
const radioValue = inputOption [ 0 ] ;
const radioLabel = inputOption [ 1 ] ;
const radioInput = document . createElement ( 'input' ) ;
const radioLabelElement = document . createElement ( 'label' ) ;
radioInput . type = 'radio' ;
radioInput . name = swalClasses . radio ;
radioInput . value = radioValue ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
if ( isSelected ( radioValue , params . inputValue ) ) {
radioInput . checked = true ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const label = document . createElement ( 'span' ) ;
setInnerHtml ( label , radioLabel ) ;
label . className = swalClasses . label ;
radioLabelElement . appendChild ( radioInput ) ;
radioLabelElement . appendChild ( label ) ;
radio . appendChild ( radioLabelElement ) ;
} ) ;
const radios = radio . querySelectorAll ( 'input' ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
if ( radios . length ) {
radios [ 0 ] . focus ( ) ;
}
2019-06-16 09:20:59 +00:00
}
2022-02-07 20:05:14 +00:00
} ;
/ * *
* Converts ` inputOptions ` into an array of ` [value, label] ` s
* @ param inputOptions
* /
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const formatInputOptions = inputOptions => {
const result = [ ] ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
if ( typeof Map !== 'undefined' && inputOptions instanceof Map ) {
inputOptions . forEach ( ( value , key ) => {
let valueFormatted = value ;
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
if ( typeof valueFormatted === 'object' ) {
// case of <optgroup>
valueFormatted = formatInputOptions ( valueFormatted ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
result . push ( [ key , valueFormatted ] ) ;
} ) ;
} else {
Object . keys ( inputOptions ) . forEach ( key => {
let valueFormatted = inputOptions [ key ] ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( typeof valueFormatted === 'object' ) {
// case of <optgroup>
valueFormatted = formatInputOptions ( valueFormatted ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
result . push ( [ key , valueFormatted ] ) ;
} ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
return result ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const isSelected = ( optionValue , inputValue ) => {
return inputValue && inputValue . toString ( ) === optionValue . toString ( ) ;
} ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const handleConfirmButtonClick = instance => {
const innerParams = privateProps . innerParams . get ( instance ) ;
instance . disableButtons ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams . input ) {
handleConfirmOrDenyWithInput ( instance , 'confirm' ) ;
} else {
confirm ( instance , true ) ;
2020-04-01 22:52:43 +00:00
}
} ;
2022-02-07 20:05:14 +00:00
const handleDenyButtonClick = instance => {
const innerParams = privateProps . innerParams . get ( instance ) ;
instance . disableButtons ( ) ;
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams . returnInputValueOnDeny ) {
handleConfirmOrDenyWithInput ( instance , 'deny' ) ;
} else {
deny ( instance , false ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
} ;
const handleCancelButtonClick = ( instance , dismissWith ) => {
instance . disableButtons ( ) ;
dismissWith ( DismissReason . cancel ) ;
} ;
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
const handleConfirmOrDenyWithInput = ( instance , type
/* 'confirm' | 'deny' */
) => {
const innerParams = privateProps . innerParams . get ( instance ) ;
if ( ! innerParams . input ) {
return error ( "The \"input\" parameter is needed to be set when using returnInputValueOn" . concat ( capitalizeFirstLetter ( type ) ) ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const inputValue = getInputValue ( instance , innerParams ) ;
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams . inputValidator ) {
handleInputValidator ( instance , inputValue , type ) ;
} else if ( ! instance . getInput ( ) . checkValidity ( ) ) {
instance . enableButtons ( ) ;
instance . showValidationMessage ( innerParams . validationMessage ) ;
} else if ( type === 'deny' ) {
deny ( instance , inputValue ) ;
} else {
confirm ( instance , inputValue ) ;
}
} ;
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
const handleInputValidator = ( instance , inputValue , type
/* 'confirm' | 'deny' */
) => {
const innerParams = privateProps . innerParams . get ( instance ) ;
instance . disableInput ( ) ;
const validationPromise = Promise . resolve ( ) . then ( ( ) => asPromise ( innerParams . inputValidator ( inputValue , innerParams . validationMessage ) ) ) ;
validationPromise . then ( validationMessage => {
instance . enableButtons ( ) ;
instance . enableInput ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( validationMessage ) {
instance . showValidationMessage ( validationMessage ) ;
} else if ( type === 'deny' ) {
deny ( instance , inputValue ) ;
} else {
confirm ( instance , inputValue ) ;
}
} ) ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const deny = ( instance , value ) => {
const innerParams = privateProps . innerParams . get ( instance || undefined ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams . showLoaderOnDeny ) {
showLoading ( getDenyButton ( ) ) ;
2019-08-20 08:54:48 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams . preDeny ) {
privateProps . awaitingPromise . set ( instance || undefined , 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
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const preDenyPromise = Promise . resolve ( ) . then ( ( ) => asPromise ( innerParams . preDeny ( value , innerParams . validationMessage ) ) ) ;
preDenyPromise . then ( preDenyValue => {
if ( preDenyValue === false ) {
instance . hideLoading ( ) ;
} else {
instance . closePopup ( {
isDenied : true ,
value : typeof preDenyValue === 'undefined' ? value : preDenyValue
} ) ;
}
} ) . catch ( error$$1 => rejectWith ( instance || undefined , error$$1 ) ) ;
} else {
instance . closePopup ( {
isDenied : true ,
value
} ) ;
2020-12-23 07:17:49 +00:00
}
2022-02-07 20:05:14 +00:00
} ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const succeedWith = ( instance , value ) => {
instance . closePopup ( {
isConfirmed : true ,
value
} ) ;
} ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const rejectWith = ( instance , error$$1 ) => {
instance . rejectPromise ( error$$1 ) ;
} ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const confirm = ( instance , value ) => {
const innerParams = privateProps . innerParams . get ( instance || undefined ) ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams . showLoaderOnConfirm ) {
showLoading ( ) ;
}
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams . preConfirm ) {
instance . resetValidationMessage ( ) ;
privateProps . awaitingPromise . set ( instance || undefined , 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
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const preConfirmPromise = Promise . resolve ( ) . then ( ( ) => asPromise ( innerParams . preConfirm ( value , innerParams . validationMessage ) ) ) ;
preConfirmPromise . then ( preConfirmValue => {
if ( isVisible ( getValidationMessage ( ) ) || preConfirmValue === false ) {
instance . hideLoading ( ) ;
} else {
succeedWith ( instance , typeof preConfirmValue === 'undefined' ? value : preConfirmValue ) ;
}
} ) . catch ( error$$1 => rejectWith ( instance || undefined , error$$1 ) ) ;
} else {
succeedWith ( instance , value ) ;
}
} ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const handlePopupClick = ( instance , domCache , dismissWith ) => {
const innerParams = privateProps . innerParams . get ( instance ) ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams . toast ) {
handleToastClick ( instance , domCache , dismissWith ) ;
} else {
// Ignore click events that had mousedown on the popup but mouseup on the container
// This can happen when the user drags a slider
handleModalMousedown ( domCache ) ; // Ignore click events that had mousedown on the container but mouseup on the popup
handleContainerMousedown ( domCache ) ;
handleModalClick ( instance , domCache , dismissWith ) ;
}
2020-12-23 07:17:49 +00:00
} ;
2022-02-07 20:05:14 +00:00
const handleToastClick = ( instance , domCache , dismissWith ) => {
// Closing toast by internal click
domCache . popup . onclick = ( ) => {
const innerParams = privateProps . innerParams . get ( instance ) ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams && ( isAnyButtonShown ( innerParams ) || innerParams . timer || innerParams . input ) ) {
return ;
2020-12-23 07:17:49 +00:00
}
2022-02-07 20:05:14 +00:00
dismissWith ( DismissReason . close ) ;
} ;
2020-12-23 07:17:49 +00:00
} ;
2022-02-07 20:05:14 +00:00
/ * *
* @ param { * } innerParams
* @ returns { boolean }
* /
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const isAnyButtonShown = innerParams => {
return innerParams . showConfirmButton || innerParams . showDenyButton || innerParams . showCancelButton || innerParams . showCloseButton ;
} ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
let ignoreOutsideClick = false ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const handleModalMousedown = domCache => {
domCache . popup . onmousedown = ( ) => {
domCache . container . onmouseup = function ( e ) {
domCache . container . onmouseup = undefined ; // We only check if the mouseup target is the container because usually it doesn't
// have any other direct children aside of the popup
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( e . target === domCache . container ) {
ignoreOutsideClick = true ;
}
} ;
} ;
} ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const handleContainerMousedown = domCache => {
domCache . container . onmousedown = ( ) => {
domCache . popup . onmouseup = function ( e ) {
domCache . popup . onmouseup = undefined ; // We also need to check if the mouseup target is a child of the popup
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( e . target === domCache . popup || domCache . popup . contains ( e . target ) ) {
ignoreOutsideClick = true ;
}
} ;
} ;
2020-12-23 07:17:49 +00:00
} ;
2022-02-07 20:05:14 +00:00
const handleModalClick = ( instance , domCache , dismissWith ) => {
domCache . container . onclick = e => {
const innerParams = privateProps . innerParams . get ( instance ) ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( ignoreOutsideClick ) {
ignoreOutsideClick = false ;
return ;
2020-12-23 07:17:49 +00:00
}
2022-02-07 20:05:14 +00:00
if ( e . target === domCache . container && callIfFunction ( innerParams . allowOutsideClick ) ) {
dismissWith ( DismissReason . backdrop ) ;
2020-12-23 07:17:49 +00:00
}
2022-02-07 20:05:14 +00:00
} ;
} ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
/ *
* Global function to determine if SweetAlert2 popup is shown
* /
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const isVisible$1 = ( ) => {
return isVisible ( getPopup ( ) ) ;
2020-12-23 07:17:49 +00:00
} ;
2022-02-07 20:05:14 +00:00
/ *
* Global function to click 'Confirm' button
* /
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const clickConfirm = ( ) => getConfirmButton ( ) && getConfirmButton ( ) . click ( ) ;
/ *
* Global function to click 'Deny' button
* /
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const clickDeny = ( ) => getDenyButton ( ) && getDenyButton ( ) . click ( ) ;
/ *
* Global function to click 'Cancel' button
* /
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const clickCancel = ( ) => getCancelButton ( ) && getCancelButton ( ) . click ( ) ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const addKeydownHandler = ( instance , globalState , innerParams , dismissWith ) => {
if ( globalState . keydownTarget && globalState . keydownHandlerAdded ) {
globalState . keydownTarget . removeEventListener ( 'keydown' , globalState . keydownHandler , {
capture : globalState . keydownListenerCapture
} ) ;
globalState . keydownHandlerAdded = false ;
2020-12-23 07:17:49 +00:00
}
2022-02-07 20:05:14 +00:00
if ( ! innerParams . toast ) {
globalState . keydownHandler = e => keydownHandler ( instance , e , dismissWith ) ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
globalState . keydownTarget = innerParams . keydownListenerCapture ? window : getPopup ( ) ;
globalState . keydownListenerCapture = innerParams . keydownListenerCapture ;
globalState . keydownTarget . addEventListener ( 'keydown' , globalState . keydownHandler , {
capture : globalState . keydownListenerCapture
2020-12-23 07:17:49 +00:00
} ) ;
2022-02-07 20:05:14 +00:00
globalState . keydownHandlerAdded = true ;
2020-12-23 07:17:49 +00:00
}
2022-02-07 20:05:14 +00:00
} ; // Focus handling
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const setFocus = ( innerParams , index , increment ) => {
const focusableElements = getFocusableElements ( ) ; // search for visible elements and select the next possible match
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( focusableElements . length ) {
index = index + increment ; // rollover to first item
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
if ( index === focusableElements . length ) {
index = 0 ; // go to last item
} else if ( index === - 1 ) {
index = focusableElements . length - 1 ;
2021-02-02 06:47:35 +00:00
}
2022-02-07 20:05:14 +00:00
return focusableElements [ index ] . focus ( ) ;
} // no visible focusable elements, focus the popup
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
getPopup ( ) . focus ( ) ;
2020-12-23 07:17:49 +00:00
} ;
2022-02-07 20:05:14 +00:00
const arrowKeysNextButton = [ 'ArrowRight' , 'ArrowDown' ] ;
const arrowKeysPreviousButton = [ 'ArrowLeft' , 'ArrowUp' ] ;
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
const keydownHandler = ( instance , e , dismissWith ) => {
const innerParams = privateProps . innerParams . get ( instance ) ;
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
if ( ! innerParams ) {
return ; // This instance has already been destroyed
2019-08-20 08:54:48 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( innerParams . stopKeydownPropagation ) {
e . stopPropagation ( ) ;
} // ENTER
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( e . key === 'Enter' ) {
handleEnter ( instance , e , innerParams ) ;
} // TAB
else if ( e . key === 'Tab' ) {
handleTab ( e , innerParams ) ;
} // ARROWS - switch focus between buttons
else if ( [ ... arrowKeysNextButton , ... arrowKeysPreviousButton ] . includes ( e . key ) ) {
handleArrows ( e . key ) ;
} // ESC
else if ( e . key === 'Escape' ) {
handleEsc ( e , innerParams , dismissWith ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const handleEnter = ( instance , e , innerParams ) => {
// #2386 #720 #721
if ( ! callIfFunction ( innerParams . allowEnterKey ) || e . isComposing ) {
return ;
2019-06-16 09:20:59 +00:00
}
2022-02-07 20:05:14 +00:00
if ( e . target && instance . getInput ( ) && e . target . outerHTML === instance . getInput ( ) . outerHTML ) {
if ( [ 'textarea' , 'file' ] . includes ( innerParams . input ) ) {
return ; // do not submit
}
clickConfirm ( ) ;
e . preventDefault ( ) ;
}
2020-11-24 07:16:03 +00:00
} ;
2022-02-07 20:05:14 +00:00
const handleTab = ( e , innerParams ) => {
const targetElement = e . target ;
const focusableElements = getFocusableElements ( ) ;
let btnIndex = - 1 ;
for ( let i = 0 ; i < focusableElements . length ; i ++ ) {
if ( targetElement === focusableElements [ i ] ) {
btnIndex = i ;
break ;
}
} // Cycle to the next button
if ( ! e . shiftKey ) {
setFocus ( innerParams , btnIndex , 1 ) ;
} // Cycle to the prev button
else {
setFocus ( innerParams , btnIndex , - 1 ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
e . stopPropagation ( ) ;
e . preventDefault ( ) ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const handleArrows = key => {
const confirmButton = getConfirmButton ( ) ;
const denyButton = getDenyButton ( ) ;
const cancelButton = getCancelButton ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( ! [ confirmButton , denyButton , cancelButton ] . includes ( document . activeElement ) ) {
2020-04-01 22:52:43 +00:00
return ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const sibling = arrowKeysNextButton . includes ( key ) ? 'nextElementSibling' : 'previousElementSibling' ;
const buttonToFocus = document . activeElement [ sibling ] ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( buttonToFocus instanceof HTMLElement ) {
buttonToFocus . focus ( ) ;
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const handleEsc = ( e , innerParams , dismissWith ) => {
if ( callIfFunction ( innerParams . allowEscapeKey ) ) {
e . preventDefault ( ) ;
dismissWith ( DismissReason . esc ) ;
}
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
const isJqueryElement = elem => typeof elem === 'object' && elem . jquery ;
2020-11-24 07:16:03 +00:00
2022-02-07 20:05:14 +00:00
const isElement = elem => elem instanceof Element || isJqueryElement ( elem ) ;
2020-11-24 07:16:03 +00:00
2022-02-07 20:05:14 +00:00
const argsToParams = args => {
const params = { } ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( typeof args [ 0 ] === 'object' && ! isElement ( args [ 0 ] ) ) {
Object . assign ( params , args [ 0 ] ) ;
} else {
[ 'title' , 'html' , 'icon' ] . forEach ( ( name , index ) => {
const arg = args [ index ] ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
if ( typeof arg === 'string' || isElement ( arg ) ) {
params [ name ] = arg ;
} else if ( arg !== undefined ) {
error ( "Unexpected type of " . concat ( name , "! Expected \"string\" or \"Element\", got " ) . concat ( typeof arg ) ) ;
}
} ) ;
2019-06-16 09:20:59 +00:00
}
2022-02-07 20:05:14 +00:00
return params ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
function fire ( ) {
const Swal = this ; // eslint-disable-line @typescript-eslint/no-this-alias
for ( var _len = arguments . length , args = new Array ( _len ) , _key = 0 ; _key < _len ; _key ++ ) {
args [ _key ] = arguments [ _key ] ;
2019-06-16 09:20:59 +00:00
}
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
return new Swal ( ... args ) ;
}
/ * *
* Returns an extended version of ` Swal ` containing ` params ` as defaults .
* Useful for reusing Swal configuration .
*
* For example :
*
* Before :
* const textPromptOptions = { input : 'text' , showCancelButton : true }
* const { value : firstName } = await Swal . fire ( { ... textPromptOptions , title : 'What is your first name?' } )
* const { value : lastName } = await Swal . fire ( { ... textPromptOptions , title : 'What is your last name?' } )
*
* After :
* const TextPrompt = Swal . mixin ( { input : 'text' , showCancelButton : true } )
* const { value : firstName } = await TextPrompt ( 'What is your first name?' )
* const { value : lastName } = await TextPrompt ( 'What is your last name?' )
*
* @ param mixinParams
* /
function mixin ( mixinParams ) {
class MixinSwal extends this {
_main ( params , priorityMixinParams ) {
return super . _main ( params , Object . assign ( { } , mixinParams , priorityMixinParams ) ) ;
}
2019-06-16 09:20:59 +00:00
}
2022-02-07 20:05:14 +00:00
return MixinSwal ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
/ * *
* If ` timer ` parameter is set , returns number of milliseconds of timer remained .
* Otherwise , returns undefined .
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const getTimerLeft = ( ) => {
return globalState . timeout && globalState . timeout . getTimerLeft ( ) ;
} ;
/ * *
* Stop timer . Returns number of milliseconds of timer remained .
* If ` timer ` parameter isn ' t set , returns undefined .
* /
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
const stopTimer = ( ) => {
if ( globalState . timeout ) {
stopTimerProgressBar ( ) ;
return globalState . timeout . stop ( ) ;
}
} ;
/ * *
* Resume timer . Returns number of milliseconds of timer remained .
* If ` timer ` parameter isn ' t set , returns undefined .
* /
const resumeTimer = ( ) => {
if ( globalState . timeout ) {
const remaining = globalState . timeout . start ( ) ;
animateTimerProgressBar ( remaining ) ;
return remaining ;
2020-04-01 22:52:43 +00:00
}
} ;
2022-02-07 20:05:14 +00:00
/ * *
* Resume timer . Returns number of milliseconds of timer remained .
* If ` timer ` parameter isn ' t set , returns undefined .
* /
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
const toggleTimer = ( ) => {
const timer = globalState . timeout ;
return timer && ( timer . running ? stopTimer ( ) : resumeTimer ( ) ) ;
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
/ * *
* Increase timer . Returns number of milliseconds of an updated timer .
* If ` timer ` parameter isn ' t set , returns undefined .
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const increaseTimer = n => {
if ( globalState . timeout ) {
const remaining = globalState . timeout . increase ( n ) ;
animateTimerProgressBar ( remaining , true ) ;
return remaining ;
}
2020-04-01 22:52:43 +00:00
} ;
2022-02-07 20:05:14 +00:00
/ * *
* Check if timer is running . Returns true if timer is running
* or false if timer is paused or stopped .
* If ` timer ` parameter isn ' t set , returns undefined
* /
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const isTimerRunning = ( ) => {
return globalState . timeout && globalState . timeout . isRunning ( ) ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
let bodyClickListenerAdded = false ;
const clickHandlers = { } ;
function bindClickHandler ( ) {
let attr = arguments . length > 0 && arguments [ 0 ] !== undefined ? arguments [ 0 ] : 'data-swal-template' ;
clickHandlers [ attr ] = this ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( ! bodyClickListenerAdded ) {
document . body . addEventListener ( 'click' , bodyClickListener ) ;
bodyClickListenerAdded = true ;
}
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const bodyClickListener = event => {
for ( let el = event . target ; el && el !== document ; el = el . parentNode ) {
for ( const attr in clickHandlers ) {
const template = el . getAttribute ( attr ) ;
if ( template ) {
clickHandlers [ attr ] . fire ( {
template
} ) ;
return ;
}
}
2020-04-01 22:52:43 +00:00
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
var staticMethods = /*#__PURE__*/ Object . freeze ( {
isValidParameter : isValidParameter ,
isUpdatableParameter : isUpdatableParameter ,
isDeprecatedParameter : isDeprecatedParameter ,
argsToParams : argsToParams ,
isVisible : isVisible$1 ,
clickConfirm : clickConfirm ,
clickDeny : clickDeny ,
clickCancel : clickCancel ,
getContainer : getContainer ,
getPopup : getPopup ,
getTitle : getTitle ,
getHtmlContainer : getHtmlContainer ,
getImage : getImage ,
getIcon : getIcon ,
getInputLabel : getInputLabel ,
getCloseButton : getCloseButton ,
getActions : getActions ,
getConfirmButton : getConfirmButton ,
getDenyButton : getDenyButton ,
getCancelButton : getCancelButton ,
getLoader : getLoader ,
getFooter : getFooter ,
getTimerProgressBar : getTimerProgressBar ,
getFocusableElements : getFocusableElements ,
getValidationMessage : getValidationMessage ,
isLoading : isLoading ,
fire : fire ,
mixin : mixin ,
showLoading : showLoading ,
enableLoading : showLoading ,
getTimerLeft : getTimerLeft ,
stopTimer : stopTimer ,
resumeTimer : resumeTimer ,
toggleTimer : toggleTimer ,
increaseTimer : increaseTimer ,
isTimerRunning : isTimerRunning ,
bindClickHandler : bindClickHandler
} ) ;
/ * *
* Hides loader and shows back the button which was hidden by . showLoading ( )
* /
function hideLoading ( ) {
// do nothing if popup is closed
const innerParams = privateProps . innerParams . get ( this ) ;
if ( ! innerParams ) {
return ;
}
const domCache = privateProps . domCache . get ( this ) ;
hide ( domCache . loader ) ;
if ( isToast ( ) ) {
if ( innerParams . icon ) {
show ( getIcon ( ) ) ;
}
} else {
showRelatedButton ( domCache ) ;
}
removeClass ( [ domCache . popup , domCache . actions ] , swalClasses . loading ) ;
domCache . popup . removeAttribute ( 'aria-busy' ) ;
domCache . popup . removeAttribute ( 'data-loading' ) ;
domCache . confirmButton . disabled = false ;
domCache . denyButton . disabled = false ;
domCache . cancelButton . disabled = false ;
}
const showRelatedButton = domCache => {
const buttonToReplace = domCache . popup . getElementsByClassName ( domCache . loader . getAttribute ( 'data-button-to-replace' ) ) ;
if ( buttonToReplace . length ) {
show ( buttonToReplace [ 0 ] , 'inline-block' ) ;
} else if ( allButtonsAreHidden ( ) ) {
hide ( domCache . actions ) ;
}
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
/ * *
* Gets the input DOM node , this method works with input parameter .
* @ returns { HTMLElement | null }
* /
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
function getInput$1 ( instance ) {
const innerParams = privateProps . innerParams . get ( instance || this ) ;
const domCache = privateProps . domCache . get ( instance || this ) ;
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
if ( ! domCache ) {
return null ;
}
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
return getInput ( domCache . popup , innerParams . input ) ;
}
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
/ * *
* This module contains ` WeakMap ` s for each effectively - "private property" that a ` Swal ` has .
* For example , to set the private property "foo" of ` this ` to "bar" , you can ` privateProps.foo.set(this, 'bar') `
* This is the approach that Babel will probably take to implement private methods / fields
* https : //github.com/tc39/proposal-private-methods
* https : //github.com/babel/babel/pull/7555
* Once we have the changes from that PR in Babel , and our core class fits reasonable in * one module *
* then we can use that language feature .
* /
var privateMethods = {
swalPromiseResolve : new WeakMap ( ) ,
swalPromiseReject : new WeakMap ( )
} ;
/ *
* Instance method to close sweetAlert
* /
function removePopupAndResetState ( instance , container , returnFocus , didClose ) {
if ( isToast ( ) ) {
triggerDidCloseAndDispose ( instance , didClose ) ;
} else {
restoreActiveElement ( returnFocus ) . then ( ( ) => triggerDidCloseAndDispose ( instance , didClose ) ) ;
globalState . keydownTarget . removeEventListener ( 'keydown' , globalState . keydownHandler , {
capture : globalState . keydownListenerCapture
2020-04-01 22:52:43 +00:00
} ) ;
2022-02-07 20:05:14 +00:00
globalState . keydownHandlerAdded = false ;
}
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
const isSafari = /^((?!chrome|android).)*safari/i . test ( navigator . userAgent ) ; // workaround for #2088
// for some reason removing the container in Safari will scroll the document to bottom
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( isSafari ) {
container . setAttribute ( 'style' , 'display:none !important' ) ;
container . removeAttribute ( 'class' ) ;
container . innerHTML = '' ;
} else {
container . remove ( ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( isModal ( ) ) {
undoScrollbar ( ) ;
undoIOSfix ( ) ;
unsetAriaHidden ( ) ;
2020-04-01 22:52:43 +00:00
}
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
removeBodyClasses ( ) ;
}
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
function removeBodyClasses ( ) {
removeClass ( [ document . documentElement , document . body ] , [ swalClasses . shown , swalClasses [ 'height-auto' ] , swalClasses [ 'no-backdrop' ] , swalClasses [ 'toast-shown' ] ] ) ;
}
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
function close ( resolveValue ) {
resolveValue = prepareResolveValue ( resolveValue ) ;
const swalPromiseResolve = privateMethods . swalPromiseResolve . get ( this ) ;
const didClose = triggerClosePopup ( this ) ;
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
if ( this . isAwaitingPromise ( ) ) {
// A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335
if ( ! resolveValue . isDismissed ) {
handleAwaitingPromise ( this ) ;
swalPromiseResolve ( resolveValue ) ;
}
} else if ( didClose ) {
// Resolve Swal promise
swalPromiseResolve ( resolveValue ) ;
}
}
function isAwaitingPromise ( ) {
return ! ! privateProps . awaitingPromise . get ( this ) ;
}
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
const triggerClosePopup = instance => {
const popup = getPopup ( ) ;
2020-06-01 11:05:25 +00:00
2022-02-07 20:05:14 +00:00
if ( ! popup ) {
return false ;
2020-04-01 22:52:43 +00:00
}
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
const innerParams = privateProps . innerParams . get ( instance ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( ! innerParams || hasClass ( popup , innerParams . hideClass . popup ) ) {
return false ;
}
removeClass ( popup , innerParams . showClass . popup ) ;
addClass ( popup , innerParams . hideClass . popup ) ;
const backdrop = getContainer ( ) ;
removeClass ( backdrop , innerParams . showClass . backdrop ) ;
addClass ( backdrop , innerParams . hideClass . backdrop ) ;
handlePopupAnimation ( instance , popup , innerParams ) ;
return true ;
2020-12-23 07:17:49 +00:00
} ;
2022-02-07 20:05:14 +00:00
function rejectPromise ( error ) {
const rejectPromise = privateMethods . swalPromiseReject . get ( this ) ;
handleAwaitingPromise ( this ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( rejectPromise ) {
// Reject Swal promise
rejectPromise ( error ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
}
2020-11-24 07:16:03 +00:00
2022-02-07 20:05:14 +00:00
const handleAwaitingPromise = instance => {
if ( instance . isAwaitingPromise ( ) ) {
privateProps . awaitingPromise . delete ( instance ) ; // The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335
if ( ! privateProps . innerParams . get ( instance ) ) {
instance . _destroy ( ) ;
}
2020-11-25 09:31:52 +00:00
}
2020-11-24 07:16:03 +00:00
} ;
2022-02-07 20:05:14 +00:00
const prepareResolveValue = resolveValue => {
// When user calls Swal.close()
if ( typeof resolveValue === 'undefined' ) {
return {
isConfirmed : false ,
isDenied : false ,
isDismissed : true
} ;
}
return Object . assign ( {
isConfirmed : false ,
isDenied : false ,
isDismissed : false
} , resolveValue ) ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const handlePopupAnimation = ( instance , popup , innerParams ) => {
const container = getContainer ( ) ; // If animation is supported, animate
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const animationIsSupported = animationEndEvent && hasCssAnimation ( popup ) ;
if ( typeof innerParams . willClose === 'function' ) {
innerParams . willClose ( popup ) ;
}
if ( animationIsSupported ) {
animatePopup ( instance , popup , container , innerParams . returnFocus , innerParams . didClose ) ;
2020-04-01 22:52:43 +00:00
} else {
2022-02-07 20:05:14 +00:00
// Otherwise, remove immediately
removePopupAndResetState ( instance , container , innerParams . returnFocus , innerParams . didClose ) ;
2020-04-01 22:52:43 +00:00
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const animatePopup = ( instance , popup , container , returnFocus , didClose ) => {
globalState . swalCloseEventFinishedCallback = removePopupAndResetState . bind ( null , instance , container , returnFocus , didClose ) ;
popup . addEventListener ( animationEndEvent , function ( e ) {
if ( e . target === popup ) {
globalState . swalCloseEventFinishedCallback ( ) ;
delete globalState . swalCloseEventFinishedCallback ;
2020-11-25 09:31:52 +00:00
}
} ) ;
} ;
2022-02-07 20:05:14 +00:00
const triggerDidCloseAndDispose = ( instance , didClose ) => {
setTimeout ( ( ) => {
if ( typeof didClose === 'function' ) {
didClose . bind ( instance . params ) ( ) ;
}
2021-02-02 06:47:35 +00:00
2022-02-07 20:05:14 +00:00
instance . _destroy ( ) ;
} ) ;
2020-11-24 07:16:03 +00:00
} ;
2022-02-07 20:05:14 +00:00
function setButtonsDisabled ( instance , buttons , disabled ) {
const domCache = privateProps . domCache . get ( instance ) ;
buttons . forEach ( button => {
domCache [ button ] . disabled = disabled ;
2020-04-01 22:52:43 +00:00
} ) ;
2022-02-07 20:05:14 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
function setInputDisabled ( input , disabled ) {
if ( ! input ) {
return false ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( input . type === 'radio' ) {
const radiosContainer = input . parentNode . parentNode ;
const radios = radiosContainer . querySelectorAll ( 'input' ) ;
for ( let i = 0 ; i < radios . length ; i ++ ) {
radios [ i ] . disabled = disabled ;
}
2020-04-01 22:52:43 +00:00
} else {
2022-02-07 20:05:14 +00:00
input . disabled = disabled ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
function enableButtons ( ) {
setButtonsDisabled ( this , [ 'confirmButton' , 'denyButton' , 'cancelButton' ] , false ) ;
}
function disableButtons ( ) {
setButtonsDisabled ( this , [ 'confirmButton' , 'denyButton' , 'cancelButton' ] , true ) ;
}
function enableInput ( ) {
return setInputDisabled ( this . getInput ( ) , false ) ;
}
function disableInput ( ) {
return setInputDisabled ( this . getInput ( ) , true ) ;
}
function showValidationMessage ( error ) {
const domCache = privateProps . domCache . get ( this ) ;
const params = privateProps . innerParams . get ( this ) ;
setInnerHtml ( domCache . validationMessage , error ) ;
domCache . validationMessage . className = swalClasses [ 'validation-message' ] ;
if ( params . customClass && params . customClass . validationMessage ) {
addClass ( domCache . validationMessage , params . customClass . validationMessage ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
show ( domCache . validationMessage ) ;
const input = this . getInput ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( input ) {
input . setAttribute ( 'aria-invalid' , true ) ;
input . setAttribute ( 'aria-describedby' , swalClasses [ 'validation-message' ] ) ;
focusInput ( input ) ;
addClass ( input , swalClasses . inputerror ) ;
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
} // Hide block with validation message
2019-10-21 09:54:16 +00:00
2022-02-07 20:05:14 +00:00
function resetValidationMessage$1 ( ) {
const domCache = privateProps . domCache . get ( this ) ;
2019-10-21 09:54:16 +00:00
2022-02-07 20:05:14 +00:00
if ( domCache . validationMessage ) {
hide ( domCache . validationMessage ) ;
}
2019-10-21 09:54:16 +00:00
2022-02-07 20:05:14 +00:00
const input = this . getInput ( ) ;
2019-10-21 09:54:16 +00:00
2022-02-07 20:05:14 +00:00
if ( input ) {
input . removeAttribute ( 'aria-invalid' ) ;
input . removeAttribute ( 'aria-describedby' ) ;
removeClass ( input , swalClasses . inputerror ) ;
}
}
2019-10-21 09:54:16 +00:00
2022-02-07 20:05:14 +00:00
function getProgressSteps$1 ( ) {
const domCache = privateProps . domCache . get ( this ) ;
return domCache . progressSteps ;
}
2019-10-21 09:54:16 +00:00
2022-02-07 20:05:14 +00:00
/ * *
* Updates popup parameters .
* /
2019-10-21 09:54:16 +00:00
2022-02-07 20:05:14 +00:00
function update ( params ) {
const popup = getPopup ( ) ;
const innerParams = privateProps . innerParams . get ( this ) ;
2019-10-21 09:54:16 +00:00
2022-02-07 20:05:14 +00:00
if ( ! popup || hasClass ( popup , innerParams . hideClass . popup ) ) {
return 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." ) ;
2021-09-17 19:28:20 +00:00
}
2022-02-07 20:05:14 +00:00
const validUpdatableParams = filterValidParams ( params ) ;
const updatedParams = Object . assign ( { } , innerParams , validUpdatableParams ) ;
render ( this , updatedParams ) ;
privateProps . innerParams . set ( this , updatedParams ) ;
Object . defineProperties ( this , {
params : {
value : Object . assign ( { } , this . params , params ) ,
writable : false ,
enumerable : true
}
} ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const filterValidParams = params => {
const validUpdatableParams = { } ;
Object . keys ( params ) . forEach ( param => {
if ( isUpdatableParameter ( param ) ) {
validUpdatableParams [ param ] = params [ param ] ;
} else {
warn ( "Invalid parameter to update: \"" . concat ( param , "\". Updatable params are listed here: https://github.com/sweetalert2/sweetalert2/blob/master/src/utils/params.js\n\nIf you think this parameter should be updatable, request it here: https://github.com/sweetalert2/sweetalert2/issues/new?template=02_feature_request.md" ) ) ;
}
} ) ;
return validUpdatableParams ;
2019-06-16 09:20:59 +00:00
} ;
2022-02-07 20:05:14 +00:00
function _destroy ( ) {
const domCache = privateProps . domCache . get ( this ) ;
const innerParams = privateProps . innerParams . get ( this ) ;
if ( ! innerParams ) {
disposeWeakMaps ( this ) ; // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #2335
2019-08-20 08:54:48 +00:00
2022-02-07 20:05:14 +00:00
return ; // This instance has already been destroyed
} // Check if there is another Swal closing
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( domCache . popup && globalState . swalCloseEventFinishedCallback ) {
globalState . swalCloseEventFinishedCallback ( ) ;
delete globalState . swalCloseEventFinishedCallback ;
} // Check if there is a swal disposal defer timer
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( globalState . deferDisposalTimer ) {
clearTimeout ( globalState . deferDisposalTimer ) ;
delete globalState . deferDisposalTimer ;
2019-06-16 09:20:59 +00:00
}
2022-02-07 20:05:14 +00:00
if ( typeof innerParams . didDestroy === 'function' ) {
innerParams . didDestroy ( ) ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
disposeSwal ( this ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const disposeSwal = instance => {
disposeWeakMaps ( instance ) ; // Unset this.params so GC will dispose it (#1569)
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
delete instance . params ; // Unset globalState props so GC will dispose globalState (#1569)
delete globalState . keydownHandler ;
delete globalState . keydownTarget ; // Unset currentInstance
2020-11-24 07:16:03 +00:00
2022-02-07 20:05:14 +00:00
delete globalState . currentInstance ;
} ;
2020-11-24 07:16:03 +00:00
2022-02-07 20:05:14 +00:00
const disposeWeakMaps = instance => {
// If the current instance is awaiting a promise result, we keep the privateMethods to call them once the promise result is retrieved #2335
if ( instance . isAwaitingPromise ( ) ) {
unsetWeakMaps ( privateProps , instance ) ;
privateProps . awaitingPromise . set ( instance , true ) ;
} else {
unsetWeakMaps ( privateMethods , instance ) ;
unsetWeakMaps ( privateProps , instance ) ;
2020-04-01 22:52:43 +00:00
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const unsetWeakMaps = ( obj , instance ) => {
for ( const i in obj ) {
obj [ i ] . delete ( instance ) ;
2020-04-01 22:52:43 +00:00
}
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
var instanceMethods = /*#__PURE__*/ Object . freeze ( {
hideLoading : hideLoading ,
disableLoading : hideLoading ,
getInput : getInput$1 ,
close : close ,
isAwaitingPromise : isAwaitingPromise ,
rejectPromise : rejectPromise ,
closePopup : close ,
closeModal : close ,
closeToast : close ,
enableButtons : enableButtons ,
disableButtons : disableButtons ,
enableInput : enableInput ,
disableInput : disableInput ,
showValidationMessage : showValidationMessage ,
resetValidationMessage : resetValidationMessage$1 ,
getProgressSteps : getProgressSteps$1 ,
update : update ,
_destroy : _destroy
} ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
let currentInstance ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
class SweetAlert {
constructor ( ) {
// Prevent run in Node env
if ( typeof window === 'undefined' ) {
2020-04-01 22:52:43 +00:00
return ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
currentInstance = this ; // @ts-ignore
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
for ( var _len = arguments . length , args = new Array ( _len ) , _key = 0 ; _key < _len ; _key ++ ) {
args [ _key ] = arguments [ _key ] ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const outerParams = Object . freeze ( this . constructor . argsToParams ( args ) ) ;
Object . defineProperties ( this , {
params : {
value : outerParams ,
writable : false ,
enumerable : true ,
configurable : true
2020-04-01 22:52:43 +00:00
}
2022-02-07 20:05:14 +00:00
} ) ; // @ts-ignore
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const promise = this . _main ( this . params ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
privateProps . promise . set ( this , promise ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
_main ( userParams ) {
let mixinParams = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : { } ;
showWarningsForParams ( Object . assign ( { } , mixinParams , userParams ) ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( globalState . currentInstance ) {
globalState . currentInstance . _destroy ( ) ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( isModal ( ) ) {
unsetAriaHidden ( ) ;
}
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
globalState . currentInstance = this ;
const innerParams = prepareParams ( userParams , mixinParams ) ;
setParameters ( innerParams ) ;
Object . freeze ( innerParams ) ; // clear the previous timer
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
if ( globalState . timeout ) {
globalState . timeout . stop ( ) ;
delete globalState . timeout ;
} // clear the restore focus timeout
2019-06-16 09:20:59 +00:00
2020-12-23 07:17:49 +00:00
2022-02-07 20:05:14 +00:00
clearTimeout ( globalState . restoreFocusTimeout ) ;
const domCache = populateDomCache ( this ) ;
render ( this , innerParams ) ;
privateProps . innerParams . set ( this , innerParams ) ;
return swalPromise ( this , domCache , innerParams ) ;
} // `catch` cannot be the name of a module export, so we define our thenable methods here instead
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
then ( onFulfilled ) {
const promise = privateProps . promise . get ( this ) ;
return promise . then ( onFulfilled ) ;
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
finally ( onFinally ) {
const promise = privateProps . promise . get ( this ) ;
return promise . finally ( onFinally ) ;
2019-08-20 08:54:48 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
}
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const swalPromise = ( instance , domCache , innerParams ) => {
return new Promise ( ( resolve , reject ) => {
2020-04-01 22:52:43 +00:00
// functions to handle all closings/dismissals
2022-02-07 20:05:14 +00:00
const dismissWith = dismiss => {
2020-04-01 22:52:43 +00:00
instance . closePopup ( {
2020-11-24 07:16:03 +00:00
isDismissed : true ,
2022-02-07 20:05:14 +00:00
dismiss
2020-04-01 22:52:43 +00:00
} ) ;
} ;
privateMethods . swalPromiseResolve . set ( instance , resolve ) ;
2022-02-07 20:05:14 +00:00
privateMethods . swalPromiseReject . set ( instance , reject ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
domCache . confirmButton . onclick = ( ) => handleConfirmButtonClick ( instance ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
domCache . denyButton . onclick = ( ) => handleDenyButtonClick ( instance ) ;
2020-11-24 07:16:03 +00:00
2022-02-07 20:05:14 +00:00
domCache . cancelButton . onclick = ( ) => handleCancelButtonClick ( instance , dismissWith ) ;
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
domCache . closeButton . onclick = ( ) => dismissWith ( DismissReason . close ) ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
handlePopupClick ( instance , domCache , dismissWith ) ;
addKeydownHandler ( instance , globalState , innerParams , dismissWith ) ;
handleInputOptionsAndValue ( instance , innerParams ) ;
openPopup ( innerParams ) ;
setupTimer ( globalState , innerParams , dismissWith ) ;
2020-06-01 11:05:25 +00:00
initFocus ( domCache , innerParams ) ; // Scroll container to top on open (#1247, #1946)
2020-04-01 22:52:43 +00:00
2022-02-07 20:05:14 +00:00
setTimeout ( ( ) => {
2020-06-01 11:05:25 +00:00
domCache . container . scrollTop = 0 ;
} ) ;
2020-04-01 22:52:43 +00:00
} ) ;
2019-08-20 08:54:48 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const prepareParams = ( userParams , mixinParams ) => {
const templateParams = getTemplateParams ( userParams ) ;
const params = Object . assign ( { } , defaultParams , mixinParams , templateParams , userParams ) ; // precedence is described in #2131
params . showClass = Object . assign ( { } , defaultParams . showClass , params . showClass ) ;
params . hideClass = Object . assign ( { } , defaultParams . hideClass , params . hideClass ) ;
return params ;
} ;
const populateDomCache = instance => {
const domCache = {
2020-04-01 22:52:43 +00:00
popup : getPopup ( ) ,
container : getContainer ( ) ,
actions : getActions ( ) ,
confirmButton : getConfirmButton ( ) ,
2020-11-24 07:16:03 +00:00
denyButton : getDenyButton ( ) ,
2020-04-01 22:52:43 +00:00
cancelButton : getCancelButton ( ) ,
2020-11-24 07:16:03 +00:00
loader : getLoader ( ) ,
2020-04-01 22:52:43 +00:00
closeButton : getCloseButton ( ) ,
validationMessage : getValidationMessage ( ) ,
progressSteps : getProgressSteps ( )
} ;
privateProps . domCache . set ( instance , domCache ) ;
return domCache ;
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const setupTimer = ( globalState$$1 , innerParams , dismissWith ) => {
const timerProgressBar = getTimerProgressBar ( ) ;
2020-04-01 22:52:43 +00:00
hide ( timerProgressBar ) ;
if ( innerParams . timer ) {
2022-02-07 20:05:14 +00:00
globalState$$1 . timeout = new Timer ( ( ) => {
2020-04-01 22:52:43 +00:00
dismissWith ( 'timer' ) ;
delete globalState$$1 . timeout ;
} , innerParams . timer ) ;
if ( innerParams . timerProgressBar ) {
show ( timerProgressBar ) ;
2022-02-07 20:05:14 +00:00
applyCustomClass ( timerProgressBar , innerParams , 'timerProgressBar' ) ;
setTimeout ( ( ) => {
2021-01-11 13:35:52 +00:00
if ( globalState$$1 . timeout && globalState$$1 . timeout . running ) {
// timer can be already stopped or unset at this point
2020-04-01 22:52:43 +00:00
animateTimerProgressBar ( innerParams . timer ) ;
}
} ) ;
2019-08-20 08:54:48 +00:00
}
2020-04-01 22:52:43 +00:00
}
2019-08-20 08:54:48 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const initFocus = ( domCache , innerParams ) => {
2020-04-01 22:52:43 +00:00
if ( innerParams . toast ) {
2019-08-20 08:54:48 +00:00
return ;
}
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( ! callIfFunction ( innerParams . allowEnterKey ) ) {
return blurActiveElement ( ) ;
2019-08-20 08:54:48 +00:00
}
2019-06-16 09:20:59 +00:00
2020-11-24 07:16:03 +00:00
if ( ! focusButton ( domCache , innerParams ) ) {
setFocus ( innerParams , - 1 , 1 ) ;
}
} ;
2022-02-07 20:05:14 +00:00
const focusButton = ( domCache , innerParams ) => {
2020-11-24 07:16:03 +00:00
if ( innerParams . focusDeny && isVisible ( domCache . denyButton ) ) {
domCache . denyButton . focus ( ) ;
return true ;
}
2020-04-01 22:52:43 +00:00
if ( innerParams . focusCancel && isVisible ( domCache . cancelButton ) ) {
2020-11-24 07:16:03 +00:00
domCache . cancelButton . focus ( ) ;
return true ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
if ( innerParams . focusConfirm && isVisible ( domCache . confirmButton ) ) {
2020-11-24 07:16:03 +00:00
domCache . confirmButton . focus ( ) ;
return true ;
2020-04-01 22:52:43 +00:00
}
2019-06-16 09:20:59 +00:00
2020-11-24 07:16:03 +00:00
return false ;
2020-04-01 22:52:43 +00:00
} ;
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
const blurActiveElement = ( ) => {
if ( document . activeElement instanceof HTMLElement && typeof document . activeElement . blur === 'function' ) {
2020-04-01 22:52:43 +00:00
document . activeElement . blur ( ) ;
}
2022-02-07 20:05:14 +00:00
} ; // Assign instance methods from src/instanceMethods/*.js to prototype
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
Object . assign ( SweetAlert . prototype , instanceMethods ) ; // Assign static methods from src/staticMethods/*.js to constructor
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
Object . assign ( SweetAlert , staticMethods ) ; // Proxy to instance methods to constructor, for now, for backwards compatibility
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
Object . keys ( instanceMethods ) . forEach ( key => {
2020-04-01 22:52:43 +00:00
SweetAlert [ key ] = function ( ) {
if ( currentInstance ) {
2022-02-07 20:05:14 +00:00
return currentInstance [ key ] ( ... arguments ) ;
2020-04-01 22:52:43 +00:00
}
} ;
} ) ;
SweetAlert . DismissReason = DismissReason ;
2022-02-07 20:05:14 +00:00
SweetAlert . version = '11.4.0' ;
const Swal = SweetAlert ; // @ts-ignore
2019-06-16 09:20:59 +00:00
2022-02-07 20:05:14 +00:00
Swal . default = Swal ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
return Swal ;
2019-06-16 09:20:59 +00:00
2020-04-01 22:52:43 +00:00
} ) ) ;
2019-06-16 09:20:59 +00:00
if ( typeof this !== 'undefined' && this . Sweetalert2 ) { this . swal = this . sweetAlert = this . Swal = this . SweetAlert = this . Sweetalert2 }
2022-02-07 20:05:14 +00:00
"undefined" != typeof document && function ( e , t ) { var n = e . createElement ( "style" ) ; if ( e . getElementsByTagName ( "head" ) [ 0 ] . appendChild ( n ) , n . styleSheet ) n . styleSheet . disabled || ( n . styleSheet . cssText = t ) ; else try { n . innerHTML = t } catch ( e ) { n . innerText = t } } ( document , " . swal2 - popup . swal2 - toast { box - sizing : border - box ; grid - column : 1 / 4 ! important ; grid - row : 1 / 4 ! important ; grid - template - columns : 1 fr 99 fr 1 fr ; padding : 1 em ; overflow - y : hidden ; background : # fff ; box - shadow : 0 0 1 px rgba ( 0 , 0 , 0 , . 075 ) , 0 1 px 2 px rgba ( 0 , 0 , 0 , . 075 ) , 1 px 2 px 4 px rgba ( 0 , 0 , 0 , . 075 ) , 1 px 3 px 8 px rgba ( 0 , 0 , 0 , . 075 ) , 2 px 4 px 16 px rgba ( 0 , 0 , 0 , . 075 ) ; pointer - events : all } . swal2 - popup . swal2 - toast > * { grid - column : 2 } . swal2 - popup . swal2 - toast . swal2 - title { margin : . 5 em 1 em ; padding : 0 ; font - size : 1 em ; text - align : initial } . swal2 - popup . swal2 - toast . swal2 - loading { justify - content : center } . swal2 - popup . swal2 - toast . swal2 - input { height : 2 em ; margin : . 5 em ; font - size : 1 em } . swal2 - popup . swal2 - toast . swal2 - validation - message { font - size : 1 em } . swal2 - popup . swal2 - toast . swal2 - footer { margin : . 5 em 0 0 ; padding : . 5 em 0 0 ; font - size : . 8 em } . swal2 - popup . swal2 - toast . swal2 - close { grid - column : 3 / 3 ; grid - row : 1 / 99 ; align - self : center ; width : . 8 em ; height : . 8 em ; margin : 0 ; font - size : 2 em } . swal2 - popup . swal2 - toast . swal2 - html - container { margin : . 5 em 1 em ; padding : 0 ; font - size : 1 em ; text - align : initial } . swal2 - popup . swal2 - toast . swal2 - html - container : empty { padding : 0 } . swal2 - popup . swal2 - toast . swal2 - loader { grid - column : 1 ; grid - row : 1 / 99 ; align - self : center ; width : 2 em ; height : 2 em ; margin : . 25 em } . swal2 - popup . swal2 - toast . swal2 - icon { grid - column : 1 ; grid - row : 1 / 99 ; align - self : center ; width : 2 em ; min - width : 2 em ; height : 2 em ; margin : 0 . 5 em 0 0 } . swal2 - popup . swal2 - toast . swal2 - icon . swal2 - icon - content { display : flex ; align - items : center ; font - size : 1.8 em ; font - weight : 700 } . swal2 - popup . swal2 - toast . swal2 - icon . swal2 - success . swal2 - success - ring { width : 2 em ; height : 2 em } . swal2 - popup . swal2 - toast . swal2 - icon . swal2 - error [ class ^= swal2 - x - mark - line ] { top : . 875 em ; width : 1.375 em } . swal2 - popup . swal2 - toast . swal2 - icon . swal2 - error [ class ^= swal2 - x - mark - line ] [ class $ = left ] { left : . 3125 em } . swal2 - popup . swal2 - toast . swal2 - icon . swal2 - error [ class ^= swal2 - x - mark - line ] [ class $ = right ] { right : . 3125 em } . swal2 - popup . swal2 - toast . swal2 - actions { justify - content : flex - start ; height : auto ; margin : 0 ; margin - top : . 5 em ; padding : 0 . 5 em } . swal2 - popup . swal2 - toast . swal2 - styled { margin : . 25 em . 5 em ; padding : . 4 em . 6 em ; font - size : 1 em } . swal2 - popup . swal2 - toast . swal2 - success { border - color : # a5dc86 } . swal2 - popup . swal2 - toast . swal2 - success [ class ^= swal2 - success - circular - line ] { position : absolute ; width : 1.6 em ; height : 3 em ; transform : rotate ( 45 deg ) ; border - radius : 50 % } . swal2 - popup . swal2 - toast . swal2 - success [ class ^= swal2 - success - circular - line ] [ class $ = left ] { top : - . 8 em ; left : - . 5 em ; transform : rotate ( - 45 deg ) ; transform - origin : 2 em 2 em ; border - radius : 4 em 0 0 4 em } . swal2 - popup . swal2 - toast . swal2 - success [ class ^= swal2 - success - circular - line ] [ class $ = right ] { top : - . 25 em ; left : . 9375 em ; transform - origin : 0 1.5 em ; border - radius : 0 4 em 4 em 0 } . swal2 - popup . swal2 - toast . swal2 - success . swal2 - success - ring { width : 2 em ; height : 2 em } . swal2 - popup . swal2 - toast . swal2 - success . swal2 - success - fix { top : 0 ; left : . 4375 em ; width : . 4375 em ; height : 2.6875 em } . swal2 - popup . swal2 - toast . swal2 - success [ class ^= swal2 - success - line ] { height : . 3125 em } . swal2 - popup . swal2 - toast . swal2 - success [ class ^= swal2 - success - line ] [ class $ = tip ] { top : 1.125 em ; left : . 1875 em ; width : . 75 em } . swal2 - popup . swal2 - toast . swal2 - success [ class ^= swal2 - success - line ] [ class $ = long ] { top : . 9375 em ; right : . 1875 em ; width : 1.375 em } . swal2 - popup . swal2 - toast . swal2 - success . swal2 - icon - show . swal2 - success - line - tip { - webkit - animation : swal2 - toast - animate - success - line - tip . 75 s ; animation : swal2 - toast - animate - success - line - tip . 75 s } . swal2 - popup . swal2 - toast . swal2 - success . swal2 - icon - show . swal2 - success - line - long { - webkit - animation : swal2 - toast - animate - success - line - long . 75 s ; animation : swal2 - toast - animate - success - line - long . 75 s } . swal2 - popup . swal2 - toast . swal2 - show { - webkit - animation : swal2 - toast - show . 5 s ; animation : swal2 - toast - show . 5 s } . swal2 - popup . swal2 - toast . swal2 - hide { - webkit - animation : swal2 - toast - hide . 1 s forwards ; animation : swal2 - toast - hide . 1 s forwards } . swal2 - container { display : grid ; position : fixed ; z - index : 1060 ; top : 0 ; right : 0 ; bottom : 0 ; left : 0 ; b