sweetalert2 11.3.1 → 11.3.5

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.
@@ -7,7 +7,14 @@ export const states = {
7
7
  previousBodyPadding: null
8
8
  }
9
9
 
10
- export const setInnerHtml = (elem, html) => { // #1926
10
+ /**
11
+ * Securely set innerHTML of an element
12
+ * https://github.com/sweetalert2/sweetalert2/issues/1926
13
+ *
14
+ * @param {HTMLElement} elem
15
+ * @param {string} html
16
+ */
17
+ export const setInnerHtml = (elem, html) => {
11
18
  elem.textContent = ''
12
19
  if (html) {
13
20
  const parser = new DOMParser()
@@ -21,6 +28,11 @@ export const setInnerHtml = (elem, html) => { // #1926
21
28
  }
22
29
  }
23
30
 
31
+ /**
32
+ * @param {HTMLElement} elem
33
+ * @param {string} className
34
+ * @returns {boolean}
35
+ */
24
36
  export const hasClass = (elem, className) => {
25
37
  if (!className) {
26
38
  return false
@@ -58,6 +70,11 @@ export const applyCustomClass = (elem, params, className) => {
58
70
  }
59
71
  }
60
72
 
73
+ /**
74
+ * @param {HTMLElement} popup
75
+ * @param {string} inputType
76
+ * @returns {HTMLInputElement | null}
77
+ */
61
78
  export const getInput = (popup, inputType) => {
62
79
  if (!inputType) {
63
80
  return null
@@ -66,19 +83,22 @@ export const getInput = (popup, inputType) => {
66
83
  case 'select':
67
84
  case 'textarea':
68
85
  case 'file':
69
- return getChildByClass(popup, swalClasses[inputType])
86
+ return popup.querySelector(`.${swalClasses.popup} > .${swalClasses[inputType]}`)
70
87
  case 'checkbox':
71
- return popup.querySelector(`.${swalClasses.checkbox} input`)
88
+ return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.checkbox} input`)
72
89
  case 'radio':
73
- return popup.querySelector(`.${swalClasses.radio} input:checked`) ||
74
- popup.querySelector(`.${swalClasses.radio} input:first-child`)
90
+ return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:checked`) ||
91
+ popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:first-child`)
75
92
  case 'range':
76
- return popup.querySelector(`.${swalClasses.range} input`)
93
+ return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.range} input`)
77
94
  default:
78
- return getChildByClass(popup, swalClasses.input)
95
+ return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.input}`)
79
96
  }
80
97
  }
81
98
 
99
+ /**
100
+ * @param {HTMLInputElement} input
101
+ */
82
102
  export const focusInput = (input) => {
83
103
  input.focus()
84
104
 
@@ -91,6 +111,11 @@ export const focusInput = (input) => {
91
111
  }
92
112
  }
93
113
 
114
+ /**
115
+ * @param {HTMLElement | HTMLElement[] | null} target
116
+ * @param {string | string[]} classList
117
+ * @param {boolean} condition
118
+ */
94
119
  export const toggleClass = (target, classList, condition) => {
95
120
  if (!target || !classList) {
96
121
  return
@@ -99,7 +124,7 @@ export const toggleClass = (target, classList, condition) => {
99
124
  classList = classList.split(/\s+/).filter(Boolean)
100
125
  }
101
126
  classList.forEach((className) => {
102
- if (target.forEach) {
127
+ if (Array.isArray(target)) {
103
128
  target.forEach((elem) => {
104
129
  condition ? elem.classList.add(className) : elem.classList.remove(className)
105
130
  })
@@ -109,22 +134,43 @@ export const toggleClass = (target, classList, condition) => {
109
134
  })
110
135
  }
111
136
 
137
+ /**
138
+ * @param {HTMLElement | HTMLElement[] | null} target
139
+ * @param {string | string[]} classList
140
+ */
112
141
  export const addClass = (target, classList) => {
113
142
  toggleClass(target, classList, true)
114
143
  }
115
144
 
145
+ /**
146
+ * @param {HTMLElement | HTMLElement[] | null} target
147
+ * @param {string | string[]} classList
148
+ */
116
149
  export const removeClass = (target, classList) => {
117
150
  toggleClass(target, classList, false)
118
151
  }
119
152
 
120
- export const getChildByClass = (elem, className) => {
121
- for (let i = 0; i < elem.childNodes.length; i++) {
122
- if (hasClass(elem.childNodes[i], className)) {
123
- return elem.childNodes[i]
153
+ /**
154
+ * Get direct child of an element by class name
155
+ *
156
+ * @param {HTMLElement} elem
157
+ * @param {string} className
158
+ * @returns {HTMLElement | null}
159
+ */
160
+ export const getDirectChildByClass = (elem, className) => {
161
+ const childNodes = toArray(elem.childNodes)
162
+ for (let i = 0; i < childNodes.length; i++) {
163
+ if (hasClass(childNodes[i], className)) {
164
+ return childNodes[i]
124
165
  }
125
166
  }
126
167
  }
127
168
 
169
+ /**
170
+ * @param {HTMLElement} elem
171
+ * @param {string} property
172
+ * @param {*} value
173
+ */
128
174
  export const applyNumericalStyle = (elem, property, value) => {
129
175
  if (value === `${parseInt(value)}`) {
130
176
  value = parseInt(value)
@@ -136,10 +182,17 @@ export const applyNumericalStyle = (elem, property, value) => {
136
182
  }
137
183
  }
138
184
 
185
+ /**
186
+ * @param {HTMLElement} elem
187
+ * @param {string} display
188
+ */
139
189
  export const show = (elem, display = 'flex') => {
140
190
  elem.style.display = display
141
191
  }
142
192
 
193
+ /**
194
+ * @param {HTMLElement} elem
195
+ */
143
196
  export const hide = (elem) => {
144
197
  elem.style.display = 'none'
145
198
  }
@@ -192,7 +245,7 @@ export const stopTimerProgressBar = () => {
192
245
  timerProgressBar.style.removeProperty('transition')
193
246
  timerProgressBar.style.width = '100%'
194
247
  const timerProgressBarFullWidth = parseInt(window.getComputedStyle(timerProgressBar).width)
195
- const timerProgressBarPercent = parseInt(timerProgressBarWidth / timerProgressBarFullWidth * 100)
248
+ const timerProgressBarPercent = timerProgressBarWidth / timerProgressBarFullWidth * 100
196
249
  timerProgressBar.style.removeProperty('transition')
197
250
  timerProgressBar.style.width = `${timerProgressBarPercent}%`
198
251
  }
@@ -2,6 +2,11 @@ import { swalClasses } from '../classes.js'
2
2
  import { uniqueArray, toArray } from '../utils.js'
3
3
  import { isVisible, hasClass } from './domUtils.js'
4
4
 
5
+ /**
6
+ * Gets the popup container which contains the backdrop and the popup itself.
7
+ *
8
+ * @returns {HTMLElement | null}
9
+ */
5
10
  export const getContainer = () => document.body.querySelector(`.${swalClasses.container}`)
6
11
 
7
12
  export const elementBySelector = (selectorString) => {
@@ -69,11 +74,11 @@ export const getFocusableElements = () => {
69
74
  )
70
75
  // sort according to tabindex
71
76
  .sort((a, b) => {
72
- a = parseInt(a.getAttribute('tabindex'))
73
- b = parseInt(b.getAttribute('tabindex'))
74
- if (a > b) {
77
+ const tabindexA = parseInt(a.getAttribute('tabindex'))
78
+ const tabindexB = parseInt(b.getAttribute('tabindex'))
79
+ if (tabindexA > tabindexB) {
75
80
  return 1
76
- } else if (a < b) {
81
+ } else if (tabindexA < tabindexB) {
77
82
  return -1
78
83
  }
79
84
  return 0
@@ -1,9 +1,9 @@
1
1
  import { swalClasses } from '../classes.js'
2
2
  import { getContainer, getPopup } from './getters.js'
3
- import { addClass, removeClass, getChildByClass, setInnerHtml } from './domUtils.js'
3
+ import { addClass, removeClass, getDirectChildByClass, setInnerHtml } from './domUtils.js'
4
4
  import { isNodeEnv } from '../isNodeEnv.js'
5
5
  import { error } from '../utils.js'
6
- import sweetAlert from '../../sweetalert2.js'
6
+ import globalState from '../../globalState.js'
7
7
 
8
8
  const sweetHTML = `
9
9
  <div aria-labelledby="${swalClasses.title}" aria-describedby="${swalClasses['html-container']}" class="${swalClasses.popup}" tabindex="-1">
@@ -60,21 +60,19 @@ const resetOldContainer = () => {
60
60
  }
61
61
 
62
62
  const resetValidationMessage = () => {
63
- if (sweetAlert.isVisible()) {
64
- sweetAlert.resetValidationMessage()
65
- }
63
+ globalState.currentInstance.resetValidationMessage()
66
64
  }
67
65
 
68
66
  const addInputChangeListeners = () => {
69
67
  const popup = getPopup()
70
68
 
71
- const input = getChildByClass(popup, swalClasses.input)
72
- const file = getChildByClass(popup, swalClasses.file)
69
+ const input = getDirectChildByClass(popup, swalClasses.input)
70
+ const file = getDirectChildByClass(popup, swalClasses.file)
73
71
  const range = popup.querySelector(`.${swalClasses.range} input`)
74
72
  const rangeOutput = popup.querySelector(`.${swalClasses.range} output`)
75
- const select = getChildByClass(popup, swalClasses.select)
73
+ const select = getDirectChildByClass(popup, swalClasses.select)
76
74
  const checkbox = popup.querySelector(`.${swalClasses.checkbox} input`)
77
- const textarea = getChildByClass(popup, swalClasses.textarea)
75
+ const textarea = getDirectChildByClass(popup, swalClasses.textarea)
78
76
 
79
77
  input.oninput = resetValidationMessage
80
78
  file.onchange = resetValidationMessage
@@ -1,6 +1,6 @@
1
1
  import * as dom from './index.js'
2
2
  import { swalClasses } from '../classes.js'
3
- import { getChildByClass } from './domUtils.js'
3
+ import { getDirectChildByClass } from './domUtils.js'
4
4
  import { asPromise, error, hasToPromiseFn, isPromise } from '../utils.js'
5
5
  import { showLoading } from '../../staticMethods/showLoading.js'
6
6
 
@@ -75,7 +75,7 @@ const handleInputValue = (instance, params) => {
75
75
 
76
76
  const populateInputOptions = {
77
77
  select: (popup, inputOptions, params) => {
78
- const select = getChildByClass(popup, swalClasses.select)
78
+ const select = getDirectChildByClass(popup, swalClasses.select)
79
79
  const renderOption = (parent, optionLabel, optionValue) => {
80
80
  const option = document.createElement('option')
81
81
  option.value = optionValue
@@ -104,7 +104,7 @@ const populateInputOptions = {
104
104
  },
105
105
 
106
106
  radio: (popup, inputOptions, params) => {
107
- const radio = getChildByClass(popup, swalClasses.radio)
107
+ const radio = getDirectChildByClass(popup, swalClasses.radio)
108
108
  inputOptions.forEach(inputOption => {
109
109
  const radioValue = inputOption[0]
110
110
  const radioLabel = inputOption[1]
@@ -48,14 +48,14 @@ const applyStyles = (icon, params) => {
48
48
  setColor(icon, params)
49
49
 
50
50
  // Success icon background color
51
- adjustSuccessIconBackgoundColor()
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 adjustSuccessIconBackgoundColor = () => {
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')
@@ -12,7 +12,7 @@ export const renderInput = (instance, params) => {
12
12
 
13
13
  inputTypes.forEach((inputType) => {
14
14
  const inputClass = swalClasses[inputType]
15
- const inputContainer = dom.getChildByClass(popup, inputClass)
15
+ const inputContainer = dom.getDirectChildByClass(popup, inputClass)
16
16
 
17
17
  // set attributes
18
18
  setAttributes(inputType, params.inputAttributes)
@@ -99,7 +99,7 @@ const setInputLabel = (input, prependTo, params) => {
99
99
 
100
100
  const getInputContainer = (inputType) => {
101
101
  const inputClass = swalClasses[inputType] ? swalClasses[inputType] : swalClasses.input
102
- return dom.getChildByClass(dom.getPopup(), inputClass)
102
+ return dom.getDirectChildByClass(dom.getPopup(), inputClass)
103
103
  }
104
104
 
105
105
  const renderInputType = {}
@@ -157,8 +157,9 @@ renderInputType.radio = (radio) => {
157
157
  }
158
158
 
159
159
  renderInputType.checkbox = (checkboxContainer, params) => {
160
+ /** @type {HTMLInputElement} */
160
161
  const checkbox = dom.getInput(dom.getPopup(), 'checkbox')
161
- checkbox.value = 1
162
+ checkbox.value = '1'
162
163
  checkbox.id = swalClasses.checkbox
163
164
  checkbox.checked = Boolean(params.inputValue)
164
165
  const label = checkboxContainer.querySelector('span')
@@ -28,14 +28,13 @@ const getSwalParams = (templateContent) => {
28
28
  toArray(templateContent.querySelectorAll('swal-param')).forEach((param) => {
29
29
  showWarningsForAttributes(param, ['name', 'value'])
30
30
  const paramName = param.getAttribute('name')
31
- let value = param.getAttribute('value')
31
+ const value = param.getAttribute('value')
32
32
  if (typeof defaultParams[paramName] === 'boolean' && value === 'false') {
33
- value = false
33
+ result[paramName] = false
34
34
  }
35
35
  if (typeof defaultParams[paramName] === 'object') {
36
- value = JSON.parse(value)
36
+ result[paramName] = JSON.parse(value)
37
37
  }
38
- result[paramName] = value
39
38
  })
40
39
  return result
41
40
  }
@@ -153,6 +152,10 @@ const showWarningsForElements = (template) => {
153
152
  })
154
153
  }
155
154
 
155
+ /**
156
+ * @param {HTMLElement} el
157
+ * @param {string[]} allowedAttributes
158
+ */
156
159
  const showWarningsForAttributes = (el, allowedAttributes) => {
157
160
  toArray(el.attributes).forEach((attribute) => {
158
161
  if (allowedAttributes.indexOf(attribute.name) === -1) {
@@ -5,19 +5,26 @@ import { swalClasses } from '../utils/classes.js'
5
5
  // Fix iOS scrolling http://stackoverflow.com/q/39626302
6
6
 
7
7
  export const iOSfix = () => {
8
+ // @ts-ignore
8
9
  const iOS = (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
9
10
  if (iOS && !dom.hasClass(document.body, swalClasses.iosfix)) {
10
11
  const offset = document.body.scrollTop
11
12
  document.body.style.top = `${offset * -1}px`
12
13
  dom.addClass(document.body, swalClasses.iosfix)
13
14
  lockBodyScroll()
14
- addBottomPaddingForTallPopups() // #1948
15
+ addBottomPaddingForTallPopups()
15
16
  }
16
17
  }
17
18
 
19
+ /**
20
+ * https://github.com/sweetalert2/sweetalert2/issues/1948
21
+ */
18
22
  const addBottomPaddingForTallPopups = () => {
19
- const safari = !navigator.userAgent.match(/(CriOS|FxiOS|EdgiOS|YaBrowser|UCBrowser)/i)
20
- if (safari) {
23
+ const ua = navigator.userAgent
24
+ const iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i)
25
+ const webkit = !!ua.match(/WebKit/i)
26
+ const iOSSafari = iOS && webkit && !ua.match(/CriOS/i)
27
+ if (iOSSafari) {
21
28
  const bottomPanelHeight = 44
22
29
  if (dom.getPopup().scrollHeight > window.innerHeight - bottomPanelHeight) {
23
30
  dom.getContainer().style.paddingBottom = `${bottomPanelHeight}px`
@@ -42,7 +49,7 @@ const lockBodyScroll = () => { // #1246
42
49
  const shouldPreventTouchMove = (event) => {
43
50
  const target = event.target
44
51
  const container = dom.getContainer()
45
- if (isStylys(event) || isZoom(event)) {
52
+ if (isStylus(event) || isZoom(event)) {
46
53
  return false
47
54
  }
48
55
  if (target === container) {
@@ -62,7 +69,13 @@ const shouldPreventTouchMove = (event) => {
62
69
  return false
63
70
  }
64
71
 
65
- const isStylys = (event) => { // #1786
72
+ /**
73
+ * https://github.com/sweetalert2/sweetalert2/issues/1786
74
+ *
75
+ * @param {*} event
76
+ * @returns {boolean}
77
+ */
78
+ const isStylus = (event) => {
66
79
  return event.touches && event.touches.length && event.touches[0].touchType === 'stylus'
67
80
  }
68
81
 
@@ -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
- // the workaround with setting/unsetting opacity is needed for #2019 and 2059
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(() => {
@@ -152,7 +152,7 @@ const toastIncompatibleParams = [
152
152
 
153
153
  /**
154
154
  * Is valid parameter
155
- * @param {String} paramName
155
+ * @param {string} paramName
156
156
  */
157
157
  export const isValidParameter = (paramName) => {
158
158
  return Object.prototype.hasOwnProperty.call(defaultParams, paramName)
@@ -160,7 +160,7 @@ export const isValidParameter = (paramName) => {
160
160
 
161
161
  /**
162
162
  * Is valid parameter for Swal.update() method
163
- * @param {String} paramName
163
+ * @param {string} paramName
164
164
  */
165
165
  export const isUpdatableParameter = (paramName) => {
166
166
  return updatableParams.indexOf(paramName) !== -1
@@ -168,7 +168,7 @@ export const isUpdatableParameter = (paramName) => {
168
168
 
169
169
  /**
170
170
  * Is deprecated parameter
171
- * @param {String} paramName
171
+ * @param {string} paramName
172
172
  */
173
173
  export const isDeprecatedParameter = (paramName) => {
174
174
  return deprecatedParams[paramName]
@@ -29,7 +29,6 @@ function validateCustomTargetElement (params) {
29
29
  * Set type, text and actions on popup
30
30
  *
31
31
  * @param params
32
- * @returns {boolean}
33
32
  */
34
33
  export default function setParameters (params) {
35
34
  setDefaultInputValidators(params)
@@ -16,27 +16,28 @@ export const uniqueArray = (arr) => {
16
16
 
17
17
  /**
18
18
  * Capitalize the first letter of a string
19
- * @param str
19
+ * @param {string} str
20
+ * @returns {string}
20
21
  */
21
22
  export const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1)
22
23
 
23
24
  /**
24
- * Convert NodeList to Array
25
- * @param nodeList
25
+ * @param {NodeList | HTMLCollection | NamedNodeMap} nodeList
26
+ * @returns {array}
26
27
  */
27
28
  export const toArray = (nodeList) => Array.prototype.slice.call(nodeList)
28
29
 
29
30
  /**
30
- * Standardise console warnings
31
- * @param message
31
+ * Standardize console warnings
32
+ * @param {string | array} message
32
33
  */
33
34
  export const warn = (message) => {
34
35
  console.warn(`${consolePrefix} ${typeof message === 'object' ? message.join(' ') : message}`)
35
36
  }
36
37
 
37
38
  /**
38
- * Standardise console errors
39
- * @param message
39
+ * Standardize console errors
40
+ * @param {string} message
40
41
  */
41
42
  export const error = (message) => {
42
43
  console.error(`${consolePrefix} ${message}`)
@@ -51,7 +52,7 @@ const previousWarnOnceMessages = []
51
52
 
52
53
  /**
53
54
  * Show a console warning, but only if it hasn't already been shown
54
- * @param message
55
+ * @param {string} message
55
56
  */
56
57
  export const warnOnce = (message) => {
57
58
  if (!previousWarnOnceMessages.includes(message)) {
@@ -70,7 +70,7 @@ $swal2-html-container-word-wrap: break-word !default;
70
70
  $swal2-html-container-word-break: break-word !default;
71
71
 
72
72
  // INPUT
73
- $swal2-input-margin: 1em 2em 0 !default;
73
+ $swal2-input-margin: 1em 2em 3px !default;
74
74
  $swal2-input-width: auto !default;
75
75
  $swal2-input-height: 2.625em !default;
76
76
  $swal2-input-padding: 0 .75em !default;