sweetalert2 11.3.3 → 11.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2257 -0
- package/README.md +8 -10
- package/dist/sweetalert2.all.js +175 -78
- package/dist/sweetalert2.all.min.js +1 -1
- package/dist/sweetalert2.js +175 -78
- package/dist/sweetalert2.min.js +1 -1
- package/package.json +12 -8
- package/src/SweetAlert.js +12 -11
- package/src/buttons-handlers.js +32 -29
- package/src/globalState.js +1 -1
- package/src/instanceMethods/_destroy.js +2 -2
- package/src/instanceMethods/close.js +25 -23
- package/src/instanceMethods/enable-disable-elements.js +7 -7
- package/src/instanceMethods/getInput.js +1 -1
- package/src/instanceMethods/hideLoading.js +2 -5
- package/src/instanceMethods/progress-steps.js +1 -1
- package/src/instanceMethods/update.js +20 -13
- package/src/instanceMethods/validation-message.js +2 -2
- package/src/keydown-handler.js +22 -16
- package/src/popup-click-handler.js +3 -1
- package/src/privateMethods.js +1 -1
- package/src/privateProps.js +1 -1
- package/src/staticMethods/argsToParams.js +1 -1
- package/src/staticMethods/bindClickHandler.js +1 -1
- package/src/staticMethods/dom.js +1 -1
- package/src/staticMethods/fire.js +2 -2
- package/src/staticMethods/mixin.js +2 -2
- package/src/staticMethods/showLoading.js +1 -4
- package/src/staticMethods.js +1 -5
- package/src/utils/DismissReason.js +1 -1
- package/src/utils/Timer.js +6 -6
- package/src/utils/aria.js +2 -2
- package/src/utils/classes.js +1 -7
- package/src/utils/defaultInputValidators.js +1 -1
- package/src/utils/dom/animationEndEvent.js +2 -3
- package/src/utils/dom/domUtils.js +16 -9
- package/src/utils/dom/getters.js +11 -11
- package/src/utils/dom/init.js +3 -7
- package/src/utils/dom/inputUtils.js +26 -19
- package/src/utils/dom/parseHtmlToContainer.js +14 -3
- package/src/utils/dom/renderers/renderActions.js +3 -3
- package/src/utils/dom/renderers/renderContainer.js +3 -3
- package/src/utils/dom/renderers/renderContent.js +4 -2
- package/src/utils/dom/renderers/renderIcon.js +26 -17
- package/src/utils/dom/renderers/renderInput.js +30 -21
- package/src/utils/dom/renderers/renderPopup.js +2 -1
- package/src/utils/dom/renderers/renderProgressSteps.js +1 -1
- package/src/utils/getTemplateParams.js +43 -9
- package/src/utils/iosFix.js +33 -10
- package/src/utils/isNodeEnv.js +5 -1
- package/src/utils/openPopup.js +1 -1
- package/src/utils/params.js +2 -2
- package/src/utils/setParameters.js +5 -5
- package/src/utils/utils.js +14 -11
|
@@ -33,15 +33,17 @@ export const getInputValue = (instance, innerParams) => {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const getCheckboxValue = (input) => input.checked ? 1 : 0
|
|
36
|
+
const getCheckboxValue = (input) => (input.checked ? 1 : 0)
|
|
37
37
|
|
|
38
|
-
const getRadioValue = (input) => input.checked ? input.value : null
|
|
38
|
+
const getRadioValue = (input) => (input.checked ? input.value : null)
|
|
39
39
|
|
|
40
|
-
const getFileValue = (input) =>
|
|
40
|
+
const getFileValue = (input) =>
|
|
41
|
+
input.files.length ? (input.getAttribute('multiple') !== null ? input.files : input.files[0]) : null
|
|
41
42
|
|
|
42
43
|
const handleInputOptions = (instance, params) => {
|
|
43
44
|
const popup = dom.getPopup()
|
|
44
|
-
const processInputOptions = (inputOptions) =>
|
|
45
|
+
const processInputOptions = (inputOptions) =>
|
|
46
|
+
populateInputOptions[params.input](popup, formatInputOptions(inputOptions), params)
|
|
45
47
|
if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {
|
|
46
48
|
showLoading(dom.getConfirmButton())
|
|
47
49
|
asPromise(params.inputOptions).then((inputOptions) => {
|
|
@@ -58,12 +60,13 @@ const handleInputOptions = (instance, params) => {
|
|
|
58
60
|
const handleInputValue = (instance, params) => {
|
|
59
61
|
const input = instance.getInput()
|
|
60
62
|
dom.hide(input)
|
|
61
|
-
asPromise(params.inputValue)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
asPromise(params.inputValue)
|
|
64
|
+
.then((inputValue) => {
|
|
65
|
+
input.value = params.input === 'number' ? parseFloat(inputValue) || 0 : `${inputValue}`
|
|
66
|
+
dom.show(input)
|
|
67
|
+
input.focus()
|
|
68
|
+
instance.hideLoading()
|
|
69
|
+
})
|
|
67
70
|
.catch((err) => {
|
|
68
71
|
error(`Error in inputValue promise: ${err}`)
|
|
69
72
|
input.value = ''
|
|
@@ -83,20 +86,22 @@ const populateInputOptions = {
|
|
|
83
86
|
option.selected = isSelected(optionValue, params.inputValue)
|
|
84
87
|
parent.appendChild(option)
|
|
85
88
|
}
|
|
86
|
-
inputOptions.forEach(inputOption => {
|
|
89
|
+
inputOptions.forEach((inputOption) => {
|
|
87
90
|
const optionValue = inputOption[0]
|
|
88
91
|
const optionLabel = inputOption[1]
|
|
89
92
|
// <optgroup> spec:
|
|
90
93
|
// https://www.w3.org/TR/html401/interact/forms.html#h-17.6
|
|
91
94
|
// "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
|
|
92
95
|
// check whether this is a <optgroup>
|
|
93
|
-
if (Array.isArray(optionLabel)) {
|
|
96
|
+
if (Array.isArray(optionLabel)) {
|
|
97
|
+
// if it is an array, then it is an <optgroup>
|
|
94
98
|
const optgroup = document.createElement('optgroup')
|
|
95
99
|
optgroup.label = optionValue
|
|
96
100
|
optgroup.disabled = false // not configurable for now
|
|
97
101
|
select.appendChild(optgroup)
|
|
98
|
-
optionLabel.forEach(o => renderOption(optgroup, o[1], o[0]))
|
|
99
|
-
} else {
|
|
102
|
+
optionLabel.forEach((o) => renderOption(optgroup, o[1], o[0]))
|
|
103
|
+
} else {
|
|
104
|
+
// case of <option>
|
|
100
105
|
renderOption(select, optionLabel, optionValue)
|
|
101
106
|
}
|
|
102
107
|
})
|
|
@@ -105,7 +110,7 @@ const populateInputOptions = {
|
|
|
105
110
|
|
|
106
111
|
radio: (popup, inputOptions, params) => {
|
|
107
112
|
const radio = getDirectChildByClass(popup, swalClasses.radio)
|
|
108
|
-
inputOptions.forEach(inputOption => {
|
|
113
|
+
inputOptions.forEach((inputOption) => {
|
|
109
114
|
const radioValue = inputOption[0]
|
|
110
115
|
const radioLabel = inputOption[1]
|
|
111
116
|
const radioInput = document.createElement('input')
|
|
@@ -127,7 +132,7 @@ const populateInputOptions = {
|
|
|
127
132
|
if (radios.length) {
|
|
128
133
|
radios[0].focus()
|
|
129
134
|
}
|
|
130
|
-
}
|
|
135
|
+
},
|
|
131
136
|
}
|
|
132
137
|
|
|
133
138
|
/**
|
|
@@ -139,15 +144,17 @@ const formatInputOptions = (inputOptions) => {
|
|
|
139
144
|
if (typeof Map !== 'undefined' && inputOptions instanceof Map) {
|
|
140
145
|
inputOptions.forEach((value, key) => {
|
|
141
146
|
let valueFormatted = value
|
|
142
|
-
if (typeof valueFormatted === 'object') {
|
|
147
|
+
if (typeof valueFormatted === 'object') {
|
|
148
|
+
// case of <optgroup>
|
|
143
149
|
valueFormatted = formatInputOptions(valueFormatted)
|
|
144
150
|
}
|
|
145
151
|
result.push([key, valueFormatted])
|
|
146
152
|
})
|
|
147
153
|
} else {
|
|
148
|
-
Object.keys(inputOptions).forEach(key => {
|
|
154
|
+
Object.keys(inputOptions).forEach((key) => {
|
|
149
155
|
let valueFormatted = inputOptions[key]
|
|
150
|
-
if (typeof valueFormatted === 'object') {
|
|
156
|
+
if (typeof valueFormatted === 'object') {
|
|
157
|
+
// case of <optgroup>
|
|
151
158
|
valueFormatted = formatInputOptions(valueFormatted)
|
|
152
159
|
}
|
|
153
160
|
result.push([key, valueFormatted])
|
|
@@ -1,27 +1,38 @@
|
|
|
1
1
|
import { setInnerHtml } from './domUtils.js'
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @param {HTMLElement | object | string} param
|
|
5
|
+
* @param {HTMLElement} target
|
|
6
|
+
*/
|
|
3
7
|
export const parseHtmlToContainer = (param, target) => {
|
|
4
8
|
// DOM element
|
|
5
9
|
if (param instanceof HTMLElement) {
|
|
6
10
|
target.appendChild(param)
|
|
11
|
+
}
|
|
7
12
|
|
|
8
13
|
// Object
|
|
9
|
-
|
|
14
|
+
else if (typeof param === 'object') {
|
|
10
15
|
handleObject(param, target)
|
|
16
|
+
}
|
|
11
17
|
|
|
12
18
|
// Plain string
|
|
13
|
-
|
|
19
|
+
else if (param) {
|
|
14
20
|
setInnerHtml(target, param)
|
|
15
21
|
}
|
|
16
22
|
}
|
|
17
23
|
|
|
24
|
+
/**
|
|
25
|
+
* @param {object} param
|
|
26
|
+
* @param {HTMLElement} target
|
|
27
|
+
*/
|
|
18
28
|
const handleObject = (param, target) => {
|
|
19
29
|
// JQuery element(s)
|
|
20
30
|
if (param.jquery) {
|
|
21
31
|
handleJqueryElem(target, param)
|
|
32
|
+
}
|
|
22
33
|
|
|
23
34
|
// For other objects use their string representation
|
|
24
|
-
|
|
35
|
+
else {
|
|
25
36
|
setInnerHtml(target, param.toString())
|
|
26
37
|
}
|
|
27
38
|
}
|
|
@@ -24,7 +24,7 @@ export const renderActions = (instance, params) => {
|
|
|
24
24
|
dom.applyCustomClass(loader, params, 'loader')
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
function renderButtons
|
|
27
|
+
function renderButtons(actions, loader, params) {
|
|
28
28
|
const confirmButton = dom.getConfirmButton()
|
|
29
29
|
const denyButton = dom.getDenyButton()
|
|
30
30
|
const cancelButton = dom.getCancelButton()
|
|
@@ -47,7 +47,7 @@ function renderButtons (actions, loader, params) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
function handleButtonsStyling
|
|
50
|
+
function handleButtonsStyling(confirmButton, denyButton, cancelButton, params) {
|
|
51
51
|
if (!params.buttonsStyling) {
|
|
52
52
|
return dom.removeClass([confirmButton, denyButton, cancelButton], swalClasses.styled)
|
|
53
53
|
}
|
|
@@ -69,7 +69,7 @@ function handleButtonsStyling (confirmButton, denyButton, cancelButton, params)
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
function renderButton
|
|
72
|
+
function renderButton(button, buttonType, params) {
|
|
73
73
|
dom.toggle(button, params[`show${capitalizeFirstLetter(buttonType)}Button`], 'inline-block')
|
|
74
74
|
dom.setInnerHtml(button, params[`${buttonType}ButtonText`]) // Set caption text
|
|
75
75
|
button.setAttribute('aria-label', params[`${buttonType}ButtonAriaLabel`]) // ARIA label
|
|
@@ -2,7 +2,7 @@ import { swalClasses } from '../../classes.js'
|
|
|
2
2
|
import { warn } from '../../utils.js'
|
|
3
3
|
import * as dom from '../../dom/index.js'
|
|
4
4
|
|
|
5
|
-
function handleBackdropParam
|
|
5
|
+
function handleBackdropParam(container, backdrop) {
|
|
6
6
|
if (typeof backdrop === 'string') {
|
|
7
7
|
container.style.background = backdrop
|
|
8
8
|
} else if (!backdrop) {
|
|
@@ -10,7 +10,7 @@ function handleBackdropParam (container, backdrop) {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function handlePositionParam
|
|
13
|
+
function handlePositionParam(container, position) {
|
|
14
14
|
if (position in swalClasses) {
|
|
15
15
|
dom.addClass(container, swalClasses[position])
|
|
16
16
|
} else {
|
|
@@ -19,7 +19,7 @@ function handlePositionParam (container, position) {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function handleGrowParam
|
|
22
|
+
function handleGrowParam(container, grow) {
|
|
23
23
|
if (grow && typeof grow === 'string') {
|
|
24
24
|
const growClass = `grow-${grow}`
|
|
25
25
|
if (growClass in swalClasses) {
|
|
@@ -10,14 +10,16 @@ export const renderContent = (instance, params) => {
|
|
|
10
10
|
if (params.html) {
|
|
11
11
|
dom.parseHtmlToContainer(params.html, htmlContainer)
|
|
12
12
|
dom.show(htmlContainer, 'block')
|
|
13
|
+
}
|
|
13
14
|
|
|
14
15
|
// Content as plain text
|
|
15
|
-
|
|
16
|
+
else if (params.text) {
|
|
16
17
|
htmlContainer.textContent = params.text
|
|
17
18
|
dom.show(htmlContainer, 'block')
|
|
19
|
+
}
|
|
18
20
|
|
|
19
21
|
// No content
|
|
20
|
-
|
|
22
|
+
else {
|
|
21
23
|
dom.hide(htmlContainer)
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { iconTypes, swalClasses } from '../../classes.js'
|
|
2
2
|
import { error } from '../../utils.js'
|
|
3
3
|
import * as dom from '../../dom/index.js'
|
|
4
4
|
import privateProps from '../../../privateProps.js'
|
|
@@ -48,14 +48,14 @@ const applyStyles = (icon, params) => {
|
|
|
48
48
|
setColor(icon, params)
|
|
49
49
|
|
|
50
50
|
// Success icon background color
|
|
51
|
-
|
|
51
|
+
adjustSuccessIconBackgroundColor()
|
|
52
52
|
|
|
53
53
|
// Custom class
|
|
54
54
|
dom.applyCustomClass(icon, params, 'icon')
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// Adjust success icon background color to match the popup background color
|
|
58
|
-
const
|
|
58
|
+
const adjustSuccessIconBackgroundColor = () => {
|
|
59
59
|
const popup = dom.getPopup()
|
|
60
60
|
const popupBackgroundColor = window.getComputedStyle(popup).getPropertyValue('background-color')
|
|
61
61
|
const successIconParts = popup.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix')
|
|
@@ -64,30 +64,34 @@ const adjustSuccessIconBackgoundColor = () => {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
const successIconHtml = `
|
|
68
|
+
<div class="swal2-success-circular-line-left"></div>
|
|
69
|
+
<span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>
|
|
70
|
+
<div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>
|
|
71
|
+
<div class="swal2-success-circular-line-right"></div>
|
|
72
|
+
`
|
|
73
|
+
|
|
74
|
+
const errorIconHtml = `
|
|
75
|
+
<span class="swal2-x-mark">
|
|
76
|
+
<span class="swal2-x-mark-line-left"></span>
|
|
77
|
+
<span class="swal2-x-mark-line-right"></span>
|
|
78
|
+
</span>
|
|
79
|
+
`
|
|
80
|
+
|
|
67
81
|
const setContent = (icon, params) => {
|
|
68
82
|
icon.textContent = ''
|
|
69
83
|
|
|
70
84
|
if (params.iconHtml) {
|
|
71
85
|
dom.setInnerHtml(icon, iconContent(params.iconHtml))
|
|
72
86
|
} else if (params.icon === 'success') {
|
|
73
|
-
dom.setInnerHtml(icon,
|
|
74
|
-
<div class="swal2-success-circular-line-left"></div>
|
|
75
|
-
<span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>
|
|
76
|
-
<div class="swal2-success-ring"></div> <div class="swal2-success-fix"></div>
|
|
77
|
-
<div class="swal2-success-circular-line-right"></div>
|
|
78
|
-
`)
|
|
87
|
+
dom.setInnerHtml(icon, successIconHtml)
|
|
79
88
|
} else if (params.icon === 'error') {
|
|
80
|
-
dom.setInnerHtml(icon,
|
|
81
|
-
<span class="swal2-x-mark">
|
|
82
|
-
<span class="swal2-x-mark-line-left"></span>
|
|
83
|
-
<span class="swal2-x-mark-line-right"></span>
|
|
84
|
-
</span>
|
|
85
|
-
`)
|
|
89
|
+
dom.setInnerHtml(icon, errorIconHtml)
|
|
86
90
|
} else {
|
|
87
91
|
const defaultIconHtml = {
|
|
88
92
|
question: '?',
|
|
89
93
|
warning: '!',
|
|
90
|
-
info: 'i'
|
|
94
|
+
info: 'i',
|
|
91
95
|
}
|
|
92
96
|
dom.setInnerHtml(icon, iconContent(defaultIconHtml[params.icon]))
|
|
93
97
|
}
|
|
@@ -99,7 +103,12 @@ const setColor = (icon, params) => {
|
|
|
99
103
|
}
|
|
100
104
|
icon.style.color = params.iconColor
|
|
101
105
|
icon.style.borderColor = params.iconColor
|
|
102
|
-
for (const sel of [
|
|
106
|
+
for (const sel of [
|
|
107
|
+
'.swal2-success-line-tip',
|
|
108
|
+
'.swal2-success-line-long',
|
|
109
|
+
'.swal2-x-mark-line-left',
|
|
110
|
+
'.swal2-x-mark-line-right',
|
|
111
|
+
]) {
|
|
103
112
|
dom.setStyle(icon, sel, 'backgroundColor', params.iconColor)
|
|
104
113
|
}
|
|
105
114
|
dom.setStyle(icon, '.swal2-success-ring', 'borderColor', params.iconColor)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { swalClasses } from '../../classes.js'
|
|
2
|
-
import {
|
|
2
|
+
import { error, isPromise, warn } from '../../utils.js'
|
|
3
3
|
import * as dom from '../../dom/index.js'
|
|
4
4
|
import privateProps from '../../../privateProps.js'
|
|
5
5
|
|
|
@@ -36,7 +36,9 @@ export const renderInput = (instance, params) => {
|
|
|
36
36
|
|
|
37
37
|
const showInput = (params) => {
|
|
38
38
|
if (!renderInputType[params.input]) {
|
|
39
|
-
return error(
|
|
39
|
+
return error(
|
|
40
|
+
`Unexpected type of input! Expected "text", "email", "password", "number", "tel", "select", "radio", "checkbox", "textarea", "file" or "url", got "${params.input}"`
|
|
41
|
+
)
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
const inputContainer = getInputContainer(params.input)
|
|
@@ -105,21 +107,24 @@ const getInputContainer = (inputType) => {
|
|
|
105
107
|
const renderInputType = {}
|
|
106
108
|
|
|
107
109
|
renderInputType.text =
|
|
108
|
-
renderInputType.email =
|
|
109
|
-
renderInputType.password =
|
|
110
|
-
renderInputType.number =
|
|
111
|
-
renderInputType.tel =
|
|
112
|
-
renderInputType.url =
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
110
|
+
renderInputType.email =
|
|
111
|
+
renderInputType.password =
|
|
112
|
+
renderInputType.number =
|
|
113
|
+
renderInputType.tel =
|
|
114
|
+
renderInputType.url =
|
|
115
|
+
(input, params) => {
|
|
116
|
+
if (typeof params.inputValue === 'string' || typeof params.inputValue === 'number') {
|
|
117
|
+
input.value = params.inputValue
|
|
118
|
+
} else if (!isPromise(params.inputValue)) {
|
|
119
|
+
warn(
|
|
120
|
+
`Unexpected type of inputValue! Expected "string", "number" or "Promise", got "${typeof params.inputValue}"`
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
setInputLabel(input, input, params)
|
|
124
|
+
setInputPlaceholder(input, params)
|
|
125
|
+
input.type = params.input
|
|
126
|
+
return input
|
|
127
|
+
}
|
|
123
128
|
|
|
124
129
|
renderInputType.file = (input, params) => {
|
|
125
130
|
setInputLabel(input, input, params)
|
|
@@ -172,10 +177,13 @@ renderInputType.textarea = (textarea, params) => {
|
|
|
172
177
|
setInputPlaceholder(textarea, params)
|
|
173
178
|
setInputLabel(textarea, textarea, params)
|
|
174
179
|
|
|
175
|
-
const getMargin = (el) =>
|
|
180
|
+
const getMargin = (el) =>
|
|
181
|
+
parseInt(window.getComputedStyle(el).marginLeft) + parseInt(window.getComputedStyle(el).marginRight)
|
|
176
182
|
|
|
177
|
-
|
|
178
|
-
|
|
183
|
+
// https://github.com/sweetalert2/sweetalert2/issues/2291
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
// https://github.com/sweetalert2/sweetalert2/issues/1699
|
|
186
|
+
if ('MutationObserver' in window) {
|
|
179
187
|
const initialPopupWidth = parseInt(window.getComputedStyle(dom.getPopup()).width)
|
|
180
188
|
const textareaResizeHandler = () => {
|
|
181
189
|
const textareaWidth = textarea.offsetWidth + getMargin(textarea)
|
|
@@ -186,7 +194,8 @@ renderInputType.textarea = (textarea, params) => {
|
|
|
186
194
|
}
|
|
187
195
|
}
|
|
188
196
|
new MutationObserver(textareaResizeHandler).observe(textarea, {
|
|
189
|
-
attributes: true,
|
|
197
|
+
attributes: true,
|
|
198
|
+
attributeFilter: ['style'],
|
|
190
199
|
})
|
|
191
200
|
}
|
|
192
201
|
})
|
|
@@ -6,7 +6,8 @@ export const renderPopup = (instance, params) => {
|
|
|
6
6
|
const popup = dom.getPopup()
|
|
7
7
|
|
|
8
8
|
// Width
|
|
9
|
-
|
|
9
|
+
// https://github.com/sweetalert2/sweetalert2/issues/2170
|
|
10
|
+
if (params.toast) {
|
|
10
11
|
dom.applyNumericalStyle(container, 'width', params.width)
|
|
11
12
|
popup.style.width = '100%'
|
|
12
13
|
popup.insertBefore(dom.getLoader(), dom.getIcon())
|
|
@@ -29,7 +29,7 @@ export const renderProgressSteps = (instance, params) => {
|
|
|
29
29
|
if (params.currentProgressStep >= params.progressSteps.length) {
|
|
30
30
|
warn(
|
|
31
31
|
'Invalid currentProgressStep parameter, it should be less than progressSteps.length ' +
|
|
32
|
-
|
|
32
|
+
'(currentProgressStep like JS arrays starts from 0)'
|
|
33
33
|
)
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import defaultParams from './params.js'
|
|
2
|
-
import {
|
|
2
|
+
import { capitalizeFirstLetter, toArray, warn } from './utils.js'
|
|
3
3
|
|
|
4
4
|
const swalStringParams = ['swal-title', 'swal-html', 'swal-footer']
|
|
5
5
|
|
|
@@ -8,6 +8,7 @@ export const getTemplateParams = (params) => {
|
|
|
8
8
|
if (!template) {
|
|
9
9
|
return {}
|
|
10
10
|
}
|
|
11
|
+
/** @type {DocumentFragment} */
|
|
11
12
|
const templateContent = template.content
|
|
12
13
|
|
|
13
14
|
showWarningsForElements(templateContent)
|
|
@@ -18,28 +19,33 @@ export const getTemplateParams = (params) => {
|
|
|
18
19
|
getSwalImage(templateContent),
|
|
19
20
|
getSwalIcon(templateContent),
|
|
20
21
|
getSwalInput(templateContent),
|
|
21
|
-
getSwalStringParams(templateContent, swalStringParams)
|
|
22
|
+
getSwalStringParams(templateContent, swalStringParams)
|
|
22
23
|
)
|
|
23
24
|
return result
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* @param {DocumentFragment} templateContent
|
|
29
|
+
*/
|
|
26
30
|
const getSwalParams = (templateContent) => {
|
|
27
31
|
const result = {}
|
|
28
32
|
toArray(templateContent.querySelectorAll('swal-param')).forEach((param) => {
|
|
29
33
|
showWarningsForAttributes(param, ['name', 'value'])
|
|
30
34
|
const paramName = param.getAttribute('name')
|
|
31
|
-
|
|
35
|
+
const value = param.getAttribute('value')
|
|
32
36
|
if (typeof defaultParams[paramName] === 'boolean' && value === 'false') {
|
|
33
|
-
|
|
37
|
+
result[paramName] = false
|
|
34
38
|
}
|
|
35
39
|
if (typeof defaultParams[paramName] === 'object') {
|
|
36
|
-
|
|
40
|
+
result[paramName] = JSON.parse(value)
|
|
37
41
|
}
|
|
38
|
-
result[paramName] = value
|
|
39
42
|
})
|
|
40
43
|
return result
|
|
41
44
|
}
|
|
42
45
|
|
|
46
|
+
/**
|
|
47
|
+
* @param {DocumentFragment} templateContent
|
|
48
|
+
*/
|
|
43
49
|
const getSwalButtons = (templateContent) => {
|
|
44
50
|
const result = {}
|
|
45
51
|
toArray(templateContent.querySelectorAll('swal-button')).forEach((button) => {
|
|
@@ -57,8 +63,12 @@ const getSwalButtons = (templateContent) => {
|
|
|
57
63
|
return result
|
|
58
64
|
}
|
|
59
65
|
|
|
66
|
+
/**
|
|
67
|
+
* @param {DocumentFragment} templateContent
|
|
68
|
+
*/
|
|
60
69
|
const getSwalImage = (templateContent) => {
|
|
61
70
|
const result = {}
|
|
71
|
+
/** @type {HTMLElement} */
|
|
62
72
|
const image = templateContent.querySelector('swal-image')
|
|
63
73
|
if (image) {
|
|
64
74
|
showWarningsForAttributes(image, ['src', 'width', 'height', 'alt'])
|
|
@@ -78,8 +88,12 @@ const getSwalImage = (templateContent) => {
|
|
|
78
88
|
return result
|
|
79
89
|
}
|
|
80
90
|
|
|
91
|
+
/**
|
|
92
|
+
* @param {DocumentFragment} templateContent
|
|
93
|
+
*/
|
|
81
94
|
const getSwalIcon = (templateContent) => {
|
|
82
95
|
const result = {}
|
|
96
|
+
/** @type {HTMLElement} */
|
|
83
97
|
const icon = templateContent.querySelector('swal-icon')
|
|
84
98
|
if (icon) {
|
|
85
99
|
showWarningsForAttributes(icon, ['type', 'color'])
|
|
@@ -94,8 +108,12 @@ const getSwalIcon = (templateContent) => {
|
|
|
94
108
|
return result
|
|
95
109
|
}
|
|
96
110
|
|
|
111
|
+
/**
|
|
112
|
+
* @param {DocumentFragment} templateContent
|
|
113
|
+
*/
|
|
97
114
|
const getSwalInput = (templateContent) => {
|
|
98
115
|
const result = {}
|
|
116
|
+
/** @type {HTMLElement} */
|
|
99
117
|
const input = templateContent.querySelector('swal-input')
|
|
100
118
|
if (input) {
|
|
101
119
|
showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value'])
|
|
@@ -123,10 +141,15 @@ const getSwalInput = (templateContent) => {
|
|
|
123
141
|
return result
|
|
124
142
|
}
|
|
125
143
|
|
|
144
|
+
/**
|
|
145
|
+
* @param {DocumentFragment} templateContent
|
|
146
|
+
* @param {string[]} paramNames
|
|
147
|
+
*/
|
|
126
148
|
const getSwalStringParams = (templateContent, paramNames) => {
|
|
127
149
|
const result = {}
|
|
128
150
|
for (const i in paramNames) {
|
|
129
151
|
const paramName = paramNames[i]
|
|
152
|
+
/** @type {HTMLElement} */
|
|
130
153
|
const tag = templateContent.querySelector(paramName)
|
|
131
154
|
if (tag) {
|
|
132
155
|
showWarningsForAttributes(tag, [])
|
|
@@ -136,7 +159,10 @@ const getSwalStringParams = (templateContent, paramNames) => {
|
|
|
136
159
|
return result
|
|
137
160
|
}
|
|
138
161
|
|
|
139
|
-
|
|
162
|
+
/**
|
|
163
|
+
* @param {DocumentFragment} templateContent
|
|
164
|
+
*/
|
|
165
|
+
const showWarningsForElements = (templateContent) => {
|
|
140
166
|
const allowedElements = swalStringParams.concat([
|
|
141
167
|
'swal-param',
|
|
142
168
|
'swal-button',
|
|
@@ -145,7 +171,7 @@ const showWarningsForElements = (template) => {
|
|
|
145
171
|
'swal-input',
|
|
146
172
|
'swal-input-option',
|
|
147
173
|
])
|
|
148
|
-
toArray(
|
|
174
|
+
toArray(templateContent.children).forEach((el) => {
|
|
149
175
|
const tagName = el.tagName.toLowerCase()
|
|
150
176
|
if (allowedElements.indexOf(tagName) === -1) {
|
|
151
177
|
warn(`Unrecognized element <${tagName}>`)
|
|
@@ -153,12 +179,20 @@ const showWarningsForElements = (template) => {
|
|
|
153
179
|
})
|
|
154
180
|
}
|
|
155
181
|
|
|
182
|
+
/**
|
|
183
|
+
* @param {HTMLElement} el
|
|
184
|
+
* @param {string[]} allowedAttributes
|
|
185
|
+
*/
|
|
156
186
|
const showWarningsForAttributes = (el, allowedAttributes) => {
|
|
157
187
|
toArray(el.attributes).forEach((attribute) => {
|
|
158
188
|
if (allowedAttributes.indexOf(attribute.name) === -1) {
|
|
159
189
|
warn([
|
|
160
190
|
`Unrecognized attribute "${attribute.name}" on <${el.tagName.toLowerCase()}>.`,
|
|
161
|
-
`${
|
|
191
|
+
`${
|
|
192
|
+
allowedAttributes.length
|
|
193
|
+
? `Allowed attributes are: ${allowedAttributes.join(', ')}`
|
|
194
|
+
: 'To set the value, use HTML within the element.'
|
|
195
|
+
}`,
|
|
162
196
|
])
|
|
163
197
|
}
|
|
164
198
|
})
|
package/src/utils/iosFix.js
CHANGED
|
@@ -5,20 +5,28 @@ import { swalClasses } from '../utils/classes.js'
|
|
|
5
5
|
// Fix iOS scrolling http://stackoverflow.com/q/39626302
|
|
6
6
|
|
|
7
7
|
export const iOSfix = () => {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const iOS =
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
(/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) ||
|
|
11
|
+
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
|
|
10
12
|
if (iOS && !dom.hasClass(document.body, swalClasses.iosfix)) {
|
|
11
13
|
const offset = document.body.scrollTop
|
|
12
14
|
document.body.style.top = `${offset * -1}px`
|
|
13
15
|
dom.addClass(document.body, swalClasses.iosfix)
|
|
14
16
|
lockBodyScroll()
|
|
15
|
-
addBottomPaddingForTallPopups()
|
|
17
|
+
addBottomPaddingForTallPopups()
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
20
|
|
|
21
|
+
/**
|
|
22
|
+
* https://github.com/sweetalert2/sweetalert2/issues/1948
|
|
23
|
+
*/
|
|
19
24
|
const addBottomPaddingForTallPopups = () => {
|
|
20
|
-
const
|
|
21
|
-
|
|
25
|
+
const ua = navigator.userAgent
|
|
26
|
+
const iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i)
|
|
27
|
+
const webkit = !!ua.match(/WebKit/i)
|
|
28
|
+
const iOSSafari = iOS && webkit && !ua.match(/CriOS/i)
|
|
29
|
+
if (iOSSafari) {
|
|
22
30
|
const bottomPanelHeight = 44
|
|
23
31
|
if (dom.getPopup().scrollHeight > window.innerHeight - bottomPanelHeight) {
|
|
24
32
|
dom.getContainer().style.paddingBottom = `${bottomPanelHeight}px`
|
|
@@ -26,7 +34,10 @@ const addBottomPaddingForTallPopups = () => {
|
|
|
26
34
|
}
|
|
27
35
|
}
|
|
28
36
|
|
|
29
|
-
|
|
37
|
+
/**
|
|
38
|
+
* https://github.com/sweetalert2/sweetalert2/issues/1246
|
|
39
|
+
*/
|
|
40
|
+
const lockBodyScroll = () => {
|
|
30
41
|
const container = dom.getContainer()
|
|
31
42
|
let preventTouchMove
|
|
32
43
|
container.ontouchstart = (e) => {
|
|
@@ -43,7 +54,7 @@ const lockBodyScroll = () => { // #1246
|
|
|
43
54
|
const shouldPreventTouchMove = (event) => {
|
|
44
55
|
const target = event.target
|
|
45
56
|
const container = dom.getContainer()
|
|
46
|
-
if (
|
|
57
|
+
if (isStylus(event) || isZoom(event)) {
|
|
47
58
|
return false
|
|
48
59
|
}
|
|
49
60
|
if (target === container) {
|
|
@@ -63,11 +74,23 @@ const shouldPreventTouchMove = (event) => {
|
|
|
63
74
|
return false
|
|
64
75
|
}
|
|
65
76
|
|
|
66
|
-
|
|
77
|
+
/**
|
|
78
|
+
* https://github.com/sweetalert2/sweetalert2/issues/1786
|
|
79
|
+
*
|
|
80
|
+
* @param {*} event
|
|
81
|
+
* @returns {boolean}
|
|
82
|
+
*/
|
|
83
|
+
const isStylus = (event) => {
|
|
67
84
|
return event.touches && event.touches.length && event.touches[0].touchType === 'stylus'
|
|
68
85
|
}
|
|
69
86
|
|
|
70
|
-
|
|
87
|
+
/**
|
|
88
|
+
* https://github.com/sweetalert2/sweetalert2/issues/1891
|
|
89
|
+
*
|
|
90
|
+
* @param {TouchEvent} event
|
|
91
|
+
* @returns {boolean}
|
|
92
|
+
*/
|
|
93
|
+
const isZoom = (event) => {
|
|
71
94
|
return event.touches && event.touches.length > 1
|
|
72
95
|
}
|
|
73
96
|
|
|
@@ -76,6 +99,6 @@ export const undoIOSfix = () => {
|
|
|
76
99
|
const offset = parseInt(document.body.style.top, 10)
|
|
77
100
|
dom.removeClass(document.body, swalClasses.iosfix)
|
|
78
101
|
document.body.style.top = ''
|
|
79
|
-
document.body.scrollTop =
|
|
102
|
+
document.body.scrollTop = offset * -1
|
|
80
103
|
}
|
|
81
104
|
}
|
package/src/utils/isNodeEnv.js
CHANGED
package/src/utils/openPopup.js
CHANGED
|
@@ -79,7 +79,7 @@ const fixScrollContainer = (container, scrollbarPadding, initialBodyOverflow) =>
|
|
|
79
79
|
|
|
80
80
|
const addClasses = (container, popup, params) => {
|
|
81
81
|
dom.addClass(container, params.showClass.backdrop)
|
|
82
|
-
//
|
|
82
|
+
// this workaround with opacity is needed for https://github.com/sweetalert2/sweetalert2/issues/2059
|
|
83
83
|
popup.style.setProperty('opacity', '0', 'important')
|
|
84
84
|
dom.show(popup, 'grid')
|
|
85
85
|
setTimeout(() => {
|