htmx.org 2.0.0-alpha1 → 2.0.0-alpha2
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/dist/htmx.amd.js +972 -682
- package/dist/htmx.cjs.js +972 -682
- package/dist/htmx.esm.js +972 -682
- package/dist/htmx.js +972 -682
- package/dist/htmx.min.js +1 -1
- package/dist/htmx.min.js.gz +0 -0
- package/package.json +1 -1
- package/CHANGELOG.md +0 -474
- package/dist/ext/path-params.js +0 -11
- package/dist/htmx.d.ts +0 -450
package/dist/htmx.js
CHANGED
|
@@ -1,30 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
var htmx = (function() {
|
|
2
2
|
'use strict'
|
|
3
3
|
|
|
4
4
|
// Public API
|
|
5
5
|
//* * @type {import("./htmx").HtmxApi} */
|
|
6
|
-
// TODO: list all methods in public API
|
|
7
6
|
const htmx = {
|
|
7
|
+
/* Event processing */
|
|
8
8
|
onLoad: onLoadHelper,
|
|
9
9
|
process: processNode,
|
|
10
10
|
on: addEventListenerImpl,
|
|
11
11
|
off: removeEventListenerImpl,
|
|
12
12
|
trigger: triggerEvent,
|
|
13
13
|
ajax: ajaxHelper,
|
|
14
|
+
/* DOM querying helpers */
|
|
14
15
|
find,
|
|
15
16
|
findAll,
|
|
16
17
|
closest,
|
|
17
|
-
values: function
|
|
18
|
+
values: function(elt, type) {
|
|
18
19
|
const inputValues = getInputValues(elt, type || 'post')
|
|
19
20
|
return inputValues.values
|
|
20
21
|
},
|
|
22
|
+
/* DOM manipulation helpers */
|
|
21
23
|
remove: removeElement,
|
|
22
24
|
addClass: addClassToElement,
|
|
23
25
|
removeClass: removeClassFromElement,
|
|
24
26
|
toggleClass: toggleClassOnElement,
|
|
25
27
|
takeClass: takeClassForElement,
|
|
28
|
+
swap,
|
|
29
|
+
/* Extension entrypoints */
|
|
26
30
|
defineExtension,
|
|
27
31
|
removeExtension,
|
|
32
|
+
/* Debugging */
|
|
28
33
|
logAll,
|
|
29
34
|
logNone,
|
|
30
35
|
logger: null,
|
|
@@ -50,7 +55,6 @@ const htmx = (function () {
|
|
|
50
55
|
wsReconnectDelay: 'full-jitter',
|
|
51
56
|
wsBinaryType: 'blob',
|
|
52
57
|
disableSelector: '[hx-disable], [data-hx-disable]',
|
|
53
|
-
useTemplateFragments: false,
|
|
54
58
|
scrollBehavior: 'instant',
|
|
55
59
|
defaultFocusScroll: false,
|
|
56
60
|
getCacheBusterParam: false,
|
|
@@ -59,11 +63,17 @@ const htmx = (function () {
|
|
|
59
63
|
selfRequestsOnly: true,
|
|
60
64
|
ignoreTitle: false,
|
|
61
65
|
scrollIntoViewOnBoost: true,
|
|
62
|
-
triggerSpecsCache: null
|
|
66
|
+
triggerSpecsCache: null,
|
|
67
|
+
disableInheritance: false,
|
|
68
|
+
responseHandling: [
|
|
69
|
+
{ code: '204', swap: false },
|
|
70
|
+
{ code: '[23]..', swap: true },
|
|
71
|
+
{ code: '[45]..', swap: false, error: true }
|
|
72
|
+
]
|
|
63
73
|
},
|
|
64
74
|
parseInterval,
|
|
65
75
|
_: internalEval,
|
|
66
|
-
version: '
|
|
76
|
+
version: '2.0a'
|
|
67
77
|
}
|
|
68
78
|
|
|
69
79
|
/** @type {import("./htmx").HtmxInternalApi} */
|
|
@@ -73,6 +83,7 @@ const htmx = (function () {
|
|
|
73
83
|
canAccessLocalStorage,
|
|
74
84
|
findThisElement,
|
|
75
85
|
filterValues,
|
|
86
|
+
swap,
|
|
76
87
|
hasAttribute,
|
|
77
88
|
getAttributeValue,
|
|
78
89
|
getClosestAttributeValue,
|
|
@@ -89,7 +100,6 @@ const htmx = (function () {
|
|
|
89
100
|
makeSettleInfo,
|
|
90
101
|
oobSwap,
|
|
91
102
|
querySelectorExt,
|
|
92
|
-
selectAndSwap,
|
|
93
103
|
settleImmediately,
|
|
94
104
|
shouldCancel,
|
|
95
105
|
triggerEvent,
|
|
@@ -98,13 +108,11 @@ const htmx = (function () {
|
|
|
98
108
|
}
|
|
99
109
|
|
|
100
110
|
const VERBS = ['get', 'post', 'put', 'delete', 'patch']
|
|
101
|
-
const VERB_SELECTOR = VERBS.map(function
|
|
111
|
+
const VERB_SELECTOR = VERBS.map(function(verb) {
|
|
102
112
|
return '[hx-' + verb + '], [data-hx-' + verb + ']'
|
|
103
113
|
}).join(', ')
|
|
104
114
|
|
|
105
115
|
const HEAD_TAG_REGEX = makeTagRegEx('head')
|
|
106
|
-
const TITLE_TAG_REGEX = makeTagRegEx('title')
|
|
107
|
-
const SVG_TAGS_REGEX = makeTagRegEx('svg', true)
|
|
108
116
|
|
|
109
117
|
//= ===================================================================
|
|
110
118
|
// Utilities
|
|
@@ -115,12 +123,12 @@ const htmx = (function () {
|
|
|
115
123
|
* @param {boolean} global
|
|
116
124
|
* @returns {RegExp}
|
|
117
125
|
*/
|
|
118
|
-
function makeTagRegEx
|
|
126
|
+
function makeTagRegEx(tag, global = false) {
|
|
119
127
|
return new RegExp(`<${tag}(\\s[^>]*>|>)([\\s\\S]*?)<\\/${tag}>`,
|
|
120
128
|
global ? 'gim' : 'im')
|
|
121
129
|
}
|
|
122
130
|
|
|
123
|
-
function parseInterval
|
|
131
|
+
function parseInterval(str) {
|
|
124
132
|
if (str == undefined) {
|
|
125
133
|
return undefined
|
|
126
134
|
}
|
|
@@ -139,16 +147,16 @@ const htmx = (function () {
|
|
|
139
147
|
}
|
|
140
148
|
|
|
141
149
|
/**
|
|
142
|
-
* @param {
|
|
150
|
+
* @param {Element} elt
|
|
143
151
|
* @param {string} name
|
|
144
152
|
* @returns {(string | null)}
|
|
145
153
|
*/
|
|
146
|
-
function getRawAttribute
|
|
154
|
+
function getRawAttribute(elt, name) {
|
|
147
155
|
return elt.getAttribute && elt.getAttribute(name)
|
|
148
156
|
}
|
|
149
157
|
|
|
150
158
|
// resolve with both hx and data-hx prefixes
|
|
151
|
-
function hasAttribute
|
|
159
|
+
function hasAttribute(elt, qualifiedName) {
|
|
152
160
|
return elt.hasAttribute && (elt.hasAttribute(qualifiedName) ||
|
|
153
161
|
elt.hasAttribute('data-' + qualifiedName))
|
|
154
162
|
}
|
|
@@ -159,7 +167,7 @@ const htmx = (function () {
|
|
|
159
167
|
* @param {string} qualifiedName
|
|
160
168
|
* @returns {(string | null)}
|
|
161
169
|
*/
|
|
162
|
-
function getAttributeValue
|
|
170
|
+
function getAttributeValue(elt, qualifiedName) {
|
|
163
171
|
return getRawAttribute(elt, qualifiedName) || getRawAttribute(elt, 'data-' + qualifiedName)
|
|
164
172
|
}
|
|
165
173
|
|
|
@@ -167,7 +175,7 @@ const htmx = (function () {
|
|
|
167
175
|
* @param {HTMLElement} elt
|
|
168
176
|
* @returns {HTMLElement | ShadowRoot | null}
|
|
169
177
|
*/
|
|
170
|
-
function parentElt
|
|
178
|
+
function parentElt(elt) {
|
|
171
179
|
const parent = elt.parentElement
|
|
172
180
|
if (!parent && elt.parentNode instanceof ShadowRoot) return elt.parentNode
|
|
173
181
|
return parent
|
|
@@ -176,14 +184,14 @@ const htmx = (function () {
|
|
|
176
184
|
/**
|
|
177
185
|
* @returns {Document}
|
|
178
186
|
*/
|
|
179
|
-
function getDocument
|
|
187
|
+
function getDocument() {
|
|
180
188
|
return document
|
|
181
189
|
}
|
|
182
190
|
|
|
183
191
|
/**
|
|
184
192
|
* @returns {Document | ShadowRoot}
|
|
185
193
|
*/
|
|
186
|
-
function getRootNode
|
|
194
|
+
function getRootNode(elt, global) {
|
|
187
195
|
return elt.getRootNode ? elt.getRootNode({ composed: global }) : getDocument()
|
|
188
196
|
}
|
|
189
197
|
|
|
@@ -192,7 +200,7 @@ const htmx = (function () {
|
|
|
192
200
|
* @param {(e:HTMLElement) => boolean} condition
|
|
193
201
|
* @returns {HTMLElement | null}
|
|
194
202
|
*/
|
|
195
|
-
function getClosestMatch
|
|
203
|
+
function getClosestMatch(elt, condition) {
|
|
196
204
|
while (elt && !condition(elt)) {
|
|
197
205
|
elt = parentElt(elt)
|
|
198
206
|
}
|
|
@@ -200,14 +208,23 @@ const htmx = (function () {
|
|
|
200
208
|
return elt || null
|
|
201
209
|
}
|
|
202
210
|
|
|
203
|
-
function getAttributeValueWithDisinheritance
|
|
211
|
+
function getAttributeValueWithDisinheritance(initialElement, ancestor, attributeName) {
|
|
204
212
|
const attributeValue = getAttributeValue(ancestor, attributeName)
|
|
205
213
|
const disinherit = getAttributeValue(ancestor, 'hx-disinherit')
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
214
|
+
var inherit = getAttributeValue(ancestor, 'hx-inherit')
|
|
215
|
+
if (initialElement !== ancestor) {
|
|
216
|
+
if (htmx.config.disableInheritance) {
|
|
217
|
+
if (inherit && (inherit === '*' || inherit.split(' ').indexOf(attributeName) >= 0)) {
|
|
218
|
+
return attributeValue
|
|
219
|
+
} else {
|
|
220
|
+
return null
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (disinherit && (disinherit === '*' || disinherit.split(' ').indexOf(attributeName) >= 0)) {
|
|
224
|
+
return 'unset'
|
|
225
|
+
}
|
|
210
226
|
}
|
|
227
|
+
return attributeValue
|
|
211
228
|
}
|
|
212
229
|
|
|
213
230
|
/**
|
|
@@ -215,9 +232,9 @@ const htmx = (function () {
|
|
|
215
232
|
* @param {string} attributeName
|
|
216
233
|
* @returns {string | null}
|
|
217
234
|
*/
|
|
218
|
-
function getClosestAttributeValue
|
|
235
|
+
function getClosestAttributeValue(elt, attributeName) {
|
|
219
236
|
let closestAttr = null
|
|
220
|
-
getClosestMatch(elt, function
|
|
237
|
+
getClosestMatch(elt, function(e) {
|
|
221
238
|
return closestAttr = getAttributeValueWithDisinheritance(elt, e, attributeName)
|
|
222
239
|
})
|
|
223
240
|
if (closestAttr !== 'unset') {
|
|
@@ -230,7 +247,7 @@ const htmx = (function () {
|
|
|
230
247
|
* @param {string} selector
|
|
231
248
|
* @returns {boolean}
|
|
232
249
|
*/
|
|
233
|
-
function matches
|
|
250
|
+
function matches(elt, selector) {
|
|
234
251
|
// @ts-ignore: non-standard properties for browser compatibility
|
|
235
252
|
// noinspection JSUnresolvedVariable
|
|
236
253
|
const matchesFunction = elt.matches || elt.matchesSelector || elt.msMatchesSelector || elt.mozMatchesSelector || elt.webkitMatchesSelector || elt.oMatchesSelector
|
|
@@ -241,7 +258,7 @@ const htmx = (function () {
|
|
|
241
258
|
* @param {string} str
|
|
242
259
|
* @returns {string}
|
|
243
260
|
*/
|
|
244
|
-
function getStartTag
|
|
261
|
+
function getStartTag(str) {
|
|
245
262
|
const tagMatcher = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i
|
|
246
263
|
const match = tagMatcher.exec(str)
|
|
247
264
|
if (match) {
|
|
@@ -255,74 +272,107 @@ const htmx = (function () {
|
|
|
255
272
|
*
|
|
256
273
|
* @param {string} resp
|
|
257
274
|
* @param {number} depth
|
|
258
|
-
* @returns {
|
|
275
|
+
* @returns {Document}
|
|
259
276
|
*/
|
|
260
|
-
function parseHTML
|
|
277
|
+
function parseHTML(resp) {
|
|
261
278
|
const parser = new DOMParser()
|
|
262
|
-
|
|
279
|
+
return parser.parseFromString(resp, 'text/html')
|
|
280
|
+
}
|
|
263
281
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
depth--
|
|
268
|
-
// @ts-ignore
|
|
269
|
-
responseNode = responseNode.firstChild
|
|
282
|
+
function takeChildrenFor(fragment, elt) {
|
|
283
|
+
while (elt.childNodes.length > 0) {
|
|
284
|
+
fragment.append(elt.childNodes[0])
|
|
270
285
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function duplicateScript(script) {
|
|
289
|
+
const newScript = getDocument().createElement('script')
|
|
290
|
+
forEach(script.attributes, function(attr) {
|
|
291
|
+
newScript.setAttribute(attr.name, attr.value)
|
|
292
|
+
})
|
|
293
|
+
newScript.textContent = script.textContent
|
|
294
|
+
newScript.async = false
|
|
295
|
+
if (htmx.config.inlineScriptNonce) {
|
|
296
|
+
newScript.nonce = htmx.config.inlineScriptNonce
|
|
274
297
|
}
|
|
275
|
-
return
|
|
298
|
+
return newScript
|
|
276
299
|
}
|
|
277
300
|
|
|
278
|
-
function
|
|
279
|
-
return
|
|
301
|
+
function isJavaScriptScriptNode(script) {
|
|
302
|
+
return script.matches('script') && (script.type === 'text/javascript' || script.type === 'module' || script.type === '')
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// we have to make new copies of script tags that we are going to insert because
|
|
306
|
+
// SOME browsers (not saying who, but it involves an element and an animal) don't
|
|
307
|
+
// execute scripts created in <template> tags when they are inserted into the DOM
|
|
308
|
+
// and all the others do lmao
|
|
309
|
+
function normalizeScriptTags(fragment) {
|
|
310
|
+
Array.from(fragment.querySelectorAll('script')).forEach((script) => {
|
|
311
|
+
if (isJavaScriptScriptNode(script)) {
|
|
312
|
+
const newScript = duplicateScript(script)
|
|
313
|
+
const parent = script.parentNode
|
|
314
|
+
try {
|
|
315
|
+
parent.insertBefore(newScript, script)
|
|
316
|
+
} catch (e) {
|
|
317
|
+
logError(e)
|
|
318
|
+
} finally {
|
|
319
|
+
script.remove()
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
})
|
|
280
323
|
}
|
|
281
324
|
|
|
282
325
|
/**
|
|
283
|
-
*
|
|
284
|
-
* @
|
|
285
|
-
*
|
|
326
|
+
* @param {string} response HTML
|
|
327
|
+
* @returns {DocumentFragment & {title: string}} a document fragment representing the response HTML, including
|
|
328
|
+
* a `title` property for any title information found
|
|
286
329
|
*/
|
|
287
|
-
function makeFragment
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
default:
|
|
318
|
-
return parseHTML(content, 0)
|
|
330
|
+
function makeFragment(response) {
|
|
331
|
+
// strip head tag to determine shape of response we are dealing with
|
|
332
|
+
const responseWithNoHead = response.replace(HEAD_TAG_REGEX, '')
|
|
333
|
+
const startTag = getStartTag(responseWithNoHead)
|
|
334
|
+
let fragment = null
|
|
335
|
+
if (startTag === 'html') {
|
|
336
|
+
// if it is a full document, parse it and return the body
|
|
337
|
+
fragment = new DocumentFragment()
|
|
338
|
+
const doc = parseHTML(response)
|
|
339
|
+
takeChildrenFor(fragment, doc.body)
|
|
340
|
+
fragment.title = doc.title
|
|
341
|
+
} else if (startTag === 'body') {
|
|
342
|
+
// parse body w/o wrapping in template
|
|
343
|
+
fragment = new DocumentFragment()
|
|
344
|
+
const doc = parseHTML(responseWithNoHead)
|
|
345
|
+
takeChildrenFor(fragment, doc.body)
|
|
346
|
+
fragment.title = doc.title
|
|
347
|
+
} else {
|
|
348
|
+
// otherwise we have non-body partial HTML content, so wrap it in a template to maximize parsing flexibility
|
|
349
|
+
const doc = parseHTML('<body><template class="internal-htmx-wrapper">' + responseWithNoHead + '</template></body>')
|
|
350
|
+
fragment = doc.querySelector('template').content
|
|
351
|
+
// extract title into fragment for later processing
|
|
352
|
+
fragment.title = doc.title
|
|
353
|
+
|
|
354
|
+
// for legacy reasons we support a title tag at the root level of non-body responses, so we need to handle it
|
|
355
|
+
var titleElement = fragment.querySelector('title')
|
|
356
|
+
if (titleElement && titleElement.parentNode === fragment) {
|
|
357
|
+
titleElement.remove()
|
|
358
|
+
fragment.title = titleElement.innerText
|
|
359
|
+
}
|
|
319
360
|
}
|
|
361
|
+
if (fragment) {
|
|
362
|
+
if (htmx.config.allowScriptTags) {
|
|
363
|
+
normalizeScriptTags(fragment)
|
|
364
|
+
} else {
|
|
365
|
+
// remove all script tags if scripts are disabled
|
|
366
|
+
fragment.querySelectorAll('script').forEach((script) => script.remove())
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return fragment
|
|
320
370
|
}
|
|
321
371
|
|
|
322
372
|
/**
|
|
323
373
|
* @param {Function} func
|
|
324
374
|
*/
|
|
325
|
-
function maybeCall
|
|
375
|
+
function maybeCall(func) {
|
|
326
376
|
if (func) {
|
|
327
377
|
func()
|
|
328
378
|
}
|
|
@@ -333,7 +383,7 @@ const htmx = (function () {
|
|
|
333
383
|
* @param {string} type
|
|
334
384
|
* @returns
|
|
335
385
|
*/
|
|
336
|
-
function isType
|
|
386
|
+
function isType(o, type) {
|
|
337
387
|
return Object.prototype.toString.call(o) === '[object ' + type + ']'
|
|
338
388
|
}
|
|
339
389
|
|
|
@@ -341,7 +391,7 @@ const htmx = (function () {
|
|
|
341
391
|
* @param {*} o
|
|
342
392
|
* @returns {o is Function}
|
|
343
393
|
*/
|
|
344
|
-
function isFunction
|
|
394
|
+
function isFunction(o) {
|
|
345
395
|
return isType(o, 'Function')
|
|
346
396
|
}
|
|
347
397
|
|
|
@@ -349,7 +399,7 @@ const htmx = (function () {
|
|
|
349
399
|
* @param {*} o
|
|
350
400
|
* @returns {o is Object}
|
|
351
401
|
*/
|
|
352
|
-
function isRawObject
|
|
402
|
+
function isRawObject(o) {
|
|
353
403
|
return isType(o, 'Object')
|
|
354
404
|
}
|
|
355
405
|
|
|
@@ -358,7 +408,7 @@ const htmx = (function () {
|
|
|
358
408
|
* @param {HTMLElement} elt
|
|
359
409
|
* @returns {*}
|
|
360
410
|
*/
|
|
361
|
-
function getInternalData
|
|
411
|
+
function getInternalData(elt) {
|
|
362
412
|
const dataProp = 'htmx-internal-data'
|
|
363
413
|
let data = elt[dataProp]
|
|
364
414
|
if (!data) {
|
|
@@ -372,7 +422,7 @@ const htmx = (function () {
|
|
|
372
422
|
* @param {ArrayLike} arr
|
|
373
423
|
* @returns {any[]}
|
|
374
424
|
*/
|
|
375
|
-
function toArray
|
|
425
|
+
function toArray(arr) {
|
|
376
426
|
const returnArr = []
|
|
377
427
|
if (arr) {
|
|
378
428
|
for (let i = 0; i < arr.length; i++) {
|
|
@@ -382,7 +432,17 @@ const htmx = (function () {
|
|
|
382
432
|
return returnArr
|
|
383
433
|
}
|
|
384
434
|
|
|
385
|
-
|
|
435
|
+
/**
|
|
436
|
+
* @template T
|
|
437
|
+
* @callback forEachCallback
|
|
438
|
+
* @param {T} value
|
|
439
|
+
*/
|
|
440
|
+
/**
|
|
441
|
+
* @template T
|
|
442
|
+
* @param {{[index: number]: T, length: number}} arr
|
|
443
|
+
* @param {forEachCallback<T>} func
|
|
444
|
+
*/
|
|
445
|
+
function forEach(arr, func) {
|
|
386
446
|
if (arr) {
|
|
387
447
|
for (let i = 0; i < arr.length; i++) {
|
|
388
448
|
func(arr[i])
|
|
@@ -390,14 +450,14 @@ const htmx = (function () {
|
|
|
390
450
|
}
|
|
391
451
|
}
|
|
392
452
|
|
|
393
|
-
function isScrolledIntoView
|
|
453
|
+
function isScrolledIntoView(el) {
|
|
394
454
|
const rect = el.getBoundingClientRect()
|
|
395
455
|
const elemTop = rect.top
|
|
396
456
|
const elemBottom = rect.bottom
|
|
397
457
|
return elemTop < window.innerHeight && elemBottom >= 0
|
|
398
458
|
}
|
|
399
459
|
|
|
400
|
-
function bodyContains
|
|
460
|
+
function bodyContains(elt) {
|
|
401
461
|
// IE Fix
|
|
402
462
|
if (elt.getRootNode && elt.getRootNode() instanceof window.ShadowRoot) {
|
|
403
463
|
return getDocument().body.contains(elt.getRootNode().host)
|
|
@@ -406,7 +466,7 @@ const htmx = (function () {
|
|
|
406
466
|
}
|
|
407
467
|
}
|
|
408
468
|
|
|
409
|
-
function splitOnWhitespace
|
|
469
|
+
function splitOnWhitespace(trigger) {
|
|
410
470
|
return trigger.trim().split(/\s+/)
|
|
411
471
|
}
|
|
412
472
|
|
|
@@ -417,7 +477,7 @@ const htmx = (function () {
|
|
|
417
477
|
* @param {Object} obj2
|
|
418
478
|
* @returns {Object}
|
|
419
479
|
*/
|
|
420
|
-
function mergeObjects
|
|
480
|
+
function mergeObjects(obj1, obj2) {
|
|
421
481
|
for (const key in obj2) {
|
|
422
482
|
if (obj2.hasOwnProperty(key)) {
|
|
423
483
|
obj1[key] = obj2[key]
|
|
@@ -426,7 +486,7 @@ const htmx = (function () {
|
|
|
426
486
|
return obj1
|
|
427
487
|
}
|
|
428
488
|
|
|
429
|
-
function parseJSON
|
|
489
|
+
function parseJSON(jString) {
|
|
430
490
|
try {
|
|
431
491
|
return JSON.parse(jString)
|
|
432
492
|
} catch (error) {
|
|
@@ -435,7 +495,7 @@ const htmx = (function () {
|
|
|
435
495
|
}
|
|
436
496
|
}
|
|
437
497
|
|
|
438
|
-
function canAccessLocalStorage
|
|
498
|
+
function canAccessLocalStorage() {
|
|
439
499
|
const test = 'htmx:localStorageTest'
|
|
440
500
|
try {
|
|
441
501
|
localStorage.setItem(test, test)
|
|
@@ -446,7 +506,7 @@ const htmx = (function () {
|
|
|
446
506
|
}
|
|
447
507
|
}
|
|
448
508
|
|
|
449
|
-
function normalizePath
|
|
509
|
+
function normalizePath(path) {
|
|
450
510
|
try {
|
|
451
511
|
const url = new URL(path)
|
|
452
512
|
if (url) {
|
|
@@ -467,32 +527,32 @@ const htmx = (function () {
|
|
|
467
527
|
// public API
|
|
468
528
|
//= =========================================================================================
|
|
469
529
|
|
|
470
|
-
function internalEval
|
|
471
|
-
return maybeEval(getDocument().body, function
|
|
530
|
+
function internalEval(str) {
|
|
531
|
+
return maybeEval(getDocument().body, function() {
|
|
472
532
|
return eval(str)
|
|
473
533
|
})
|
|
474
534
|
}
|
|
475
535
|
|
|
476
|
-
function onLoadHelper
|
|
477
|
-
const value = htmx.on('htmx:load', function
|
|
536
|
+
function onLoadHelper(callback) {
|
|
537
|
+
const value = htmx.on('htmx:load', function(evt) {
|
|
478
538
|
callback(evt.detail.elt)
|
|
479
539
|
})
|
|
480
540
|
return value
|
|
481
541
|
}
|
|
482
542
|
|
|
483
|
-
function logAll
|
|
484
|
-
htmx.logger = function
|
|
543
|
+
function logAll() {
|
|
544
|
+
htmx.logger = function(elt, event, data) {
|
|
485
545
|
if (console) {
|
|
486
546
|
console.log(event, elt, data)
|
|
487
547
|
}
|
|
488
548
|
}
|
|
489
549
|
}
|
|
490
550
|
|
|
491
|
-
function logNone
|
|
551
|
+
function logNone() {
|
|
492
552
|
htmx.logger = null
|
|
493
553
|
}
|
|
494
554
|
|
|
495
|
-
function find
|
|
555
|
+
function find(eltOrSelector, selector) {
|
|
496
556
|
if (selector) {
|
|
497
557
|
return eltOrSelector.querySelector(selector)
|
|
498
558
|
} else {
|
|
@@ -500,7 +560,7 @@ const htmx = (function () {
|
|
|
500
560
|
}
|
|
501
561
|
}
|
|
502
562
|
|
|
503
|
-
function findAll
|
|
563
|
+
function findAll(eltOrSelector, selector) {
|
|
504
564
|
if (selector) {
|
|
505
565
|
return eltOrSelector.querySelectorAll(selector)
|
|
506
566
|
} else {
|
|
@@ -508,10 +568,10 @@ const htmx = (function () {
|
|
|
508
568
|
}
|
|
509
569
|
}
|
|
510
570
|
|
|
511
|
-
function removeElement
|
|
571
|
+
function removeElement(elt, delay) {
|
|
512
572
|
elt = resolveTarget(elt)
|
|
513
573
|
if (delay) {
|
|
514
|
-
setTimeout(function
|
|
574
|
+
setTimeout(function() {
|
|
515
575
|
removeElement(elt)
|
|
516
576
|
elt = null
|
|
517
577
|
}, delay)
|
|
@@ -520,10 +580,10 @@ const htmx = (function () {
|
|
|
520
580
|
}
|
|
521
581
|
}
|
|
522
582
|
|
|
523
|
-
function addClassToElement
|
|
583
|
+
function addClassToElement(elt, clazz, delay) {
|
|
524
584
|
elt = resolveTarget(elt)
|
|
525
585
|
if (delay) {
|
|
526
|
-
setTimeout(function
|
|
586
|
+
setTimeout(function() {
|
|
527
587
|
addClassToElement(elt, clazz)
|
|
528
588
|
elt = null
|
|
529
589
|
}, delay)
|
|
@@ -532,10 +592,10 @@ const htmx = (function () {
|
|
|
532
592
|
}
|
|
533
593
|
}
|
|
534
594
|
|
|
535
|
-
function removeClassFromElement
|
|
595
|
+
function removeClassFromElement(elt, clazz, delay) {
|
|
536
596
|
elt = resolveTarget(elt)
|
|
537
597
|
if (delay) {
|
|
538
|
-
setTimeout(function
|
|
598
|
+
setTimeout(function() {
|
|
539
599
|
removeClassFromElement(elt, clazz)
|
|
540
600
|
elt = null
|
|
541
601
|
}, delay)
|
|
@@ -550,20 +610,20 @@ const htmx = (function () {
|
|
|
550
610
|
}
|
|
551
611
|
}
|
|
552
612
|
|
|
553
|
-
function toggleClassOnElement
|
|
613
|
+
function toggleClassOnElement(elt, clazz) {
|
|
554
614
|
elt = resolveTarget(elt)
|
|
555
615
|
elt.classList.toggle(clazz)
|
|
556
616
|
}
|
|
557
617
|
|
|
558
|
-
function takeClassForElement
|
|
618
|
+
function takeClassForElement(elt, clazz) {
|
|
559
619
|
elt = resolveTarget(elt)
|
|
560
|
-
forEach(elt.parentElement.children, function
|
|
620
|
+
forEach(elt.parentElement.children, function(child) {
|
|
561
621
|
removeClassFromElement(child, clazz)
|
|
562
622
|
})
|
|
563
623
|
addClassToElement(elt, clazz)
|
|
564
624
|
}
|
|
565
625
|
|
|
566
|
-
function closest
|
|
626
|
+
function closest(elt, selector) {
|
|
567
627
|
elt = resolveTarget(elt)
|
|
568
628
|
if (elt.closest) {
|
|
569
629
|
return elt.closest(selector)
|
|
@@ -579,15 +639,15 @@ const htmx = (function () {
|
|
|
579
639
|
}
|
|
580
640
|
}
|
|
581
641
|
|
|
582
|
-
function startsWith
|
|
642
|
+
function startsWith(str, prefix) {
|
|
583
643
|
return str.substring(0, prefix.length) === prefix
|
|
584
644
|
}
|
|
585
645
|
|
|
586
|
-
function endsWith
|
|
646
|
+
function endsWith(str, suffix) {
|
|
587
647
|
return str.substring(str.length - suffix.length) === suffix
|
|
588
648
|
}
|
|
589
649
|
|
|
590
|
-
function normalizeSelector
|
|
650
|
+
function normalizeSelector(selector) {
|
|
591
651
|
const trimmedSelector = selector.trim()
|
|
592
652
|
if (startsWith(trimmedSelector, '<') && endsWith(trimmedSelector, '/>')) {
|
|
593
653
|
return trimmedSelector.substring(1, trimmedSelector.length - 2)
|
|
@@ -596,7 +656,7 @@ const htmx = (function () {
|
|
|
596
656
|
}
|
|
597
657
|
}
|
|
598
658
|
|
|
599
|
-
function querySelectorAllExt
|
|
659
|
+
function querySelectorAllExt(elt, selector, global) {
|
|
600
660
|
if (selector.indexOf('closest ') === 0) {
|
|
601
661
|
return [closest(elt, normalizeSelector(selector.substr(8)))]
|
|
602
662
|
} else if (selector.indexOf('find ') === 0) {
|
|
@@ -624,7 +684,7 @@ const htmx = (function () {
|
|
|
624
684
|
}
|
|
625
685
|
}
|
|
626
686
|
|
|
627
|
-
var scanForwardQuery = function
|
|
687
|
+
var scanForwardQuery = function(start, match, global) {
|
|
628
688
|
const results = getRootNode(start, global).querySelectorAll(match)
|
|
629
689
|
for (let i = 0; i < results.length; i++) {
|
|
630
690
|
const elt = results[i]
|
|
@@ -634,7 +694,7 @@ const htmx = (function () {
|
|
|
634
694
|
}
|
|
635
695
|
}
|
|
636
696
|
|
|
637
|
-
var scanBackwardsQuery = function
|
|
697
|
+
var scanBackwardsQuery = function(start, match, global) {
|
|
638
698
|
const results = getRootNode(start, global).querySelectorAll(match)
|
|
639
699
|
for (let i = results.length - 1; i >= 0; i--) {
|
|
640
700
|
const elt = results[i]
|
|
@@ -644,7 +704,7 @@ const htmx = (function () {
|
|
|
644
704
|
}
|
|
645
705
|
}
|
|
646
706
|
|
|
647
|
-
function querySelectorExt
|
|
707
|
+
function querySelectorExt(eltOrSelector, selector) {
|
|
648
708
|
if (selector) {
|
|
649
709
|
return querySelectorAllExt(eltOrSelector, selector)[0]
|
|
650
710
|
} else {
|
|
@@ -652,15 +712,22 @@ const htmx = (function () {
|
|
|
652
712
|
}
|
|
653
713
|
}
|
|
654
714
|
|
|
655
|
-
|
|
715
|
+
/**
|
|
716
|
+
*
|
|
717
|
+
* @param {string|Element} arg2
|
|
718
|
+
* @param {Element} [context]
|
|
719
|
+
* @returns {Element}
|
|
720
|
+
*/
|
|
721
|
+
function resolveTarget(arg2, context) {
|
|
656
722
|
if (isType(arg2, 'String')) {
|
|
657
723
|
return find(context || document, arg2)
|
|
658
724
|
} else {
|
|
725
|
+
// @ts-ignore
|
|
659
726
|
return arg2
|
|
660
727
|
}
|
|
661
728
|
}
|
|
662
729
|
|
|
663
|
-
function processEventArgs
|
|
730
|
+
function processEventArgs(arg1, arg2, arg3) {
|
|
664
731
|
if (isFunction(arg2)) {
|
|
665
732
|
return {
|
|
666
733
|
target: getDocument().body,
|
|
@@ -676,8 +743,8 @@ const htmx = (function () {
|
|
|
676
743
|
}
|
|
677
744
|
}
|
|
678
745
|
|
|
679
|
-
function addEventListenerImpl
|
|
680
|
-
ready(function
|
|
746
|
+
function addEventListenerImpl(arg1, arg2, arg3) {
|
|
747
|
+
ready(function() {
|
|
681
748
|
const eventArgs = processEventArgs(arg1, arg2, arg3)
|
|
682
749
|
eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener)
|
|
683
750
|
})
|
|
@@ -685,8 +752,8 @@ const htmx = (function () {
|
|
|
685
752
|
return b ? arg2 : arg3
|
|
686
753
|
}
|
|
687
754
|
|
|
688
|
-
function removeEventListenerImpl
|
|
689
|
-
ready(function
|
|
755
|
+
function removeEventListenerImpl(arg1, arg2, arg3) {
|
|
756
|
+
ready(function() {
|
|
690
757
|
const eventArgs = processEventArgs(arg1, arg2, arg3)
|
|
691
758
|
eventArgs.target.removeEventListener(eventArgs.event, eventArgs.listener)
|
|
692
759
|
})
|
|
@@ -698,7 +765,7 @@ const htmx = (function () {
|
|
|
698
765
|
//= ===================================================================
|
|
699
766
|
|
|
700
767
|
const DUMMY_ELT = getDocument().createElement('output') // dummy element for bad selectors
|
|
701
|
-
function findAttributeTargets
|
|
768
|
+
function findAttributeTargets(elt, attrName) {
|
|
702
769
|
const attrTarget = getClosestAttributeValue(elt, attrName)
|
|
703
770
|
if (attrTarget) {
|
|
704
771
|
if (attrTarget === 'this') {
|
|
@@ -715,13 +782,13 @@ const htmx = (function () {
|
|
|
715
782
|
}
|
|
716
783
|
}
|
|
717
784
|
|
|
718
|
-
function findThisElement
|
|
719
|
-
return getClosestMatch(elt, function
|
|
785
|
+
function findThisElement(elt, attribute) {
|
|
786
|
+
return getClosestMatch(elt, function(elt) {
|
|
720
787
|
return getAttributeValue(elt, attribute) != null
|
|
721
788
|
})
|
|
722
789
|
}
|
|
723
790
|
|
|
724
|
-
function getTarget
|
|
791
|
+
function getTarget(elt) {
|
|
725
792
|
const targetStr = getClosestAttributeValue(elt, 'hx-target')
|
|
726
793
|
if (targetStr) {
|
|
727
794
|
if (targetStr === 'this') {
|
|
@@ -739,7 +806,7 @@ const htmx = (function () {
|
|
|
739
806
|
}
|
|
740
807
|
}
|
|
741
808
|
|
|
742
|
-
function shouldSettleAttribute
|
|
809
|
+
function shouldSettleAttribute(name) {
|
|
743
810
|
const attributesToSettle = htmx.config.attributesToSettle
|
|
744
811
|
for (let i = 0; i < attributesToSettle.length; i++) {
|
|
745
812
|
if (name === attributesToSettle[i]) {
|
|
@@ -749,20 +816,20 @@ const htmx = (function () {
|
|
|
749
816
|
return false
|
|
750
817
|
}
|
|
751
818
|
|
|
752
|
-
function cloneAttributes
|
|
753
|
-
forEach(mergeTo.attributes, function
|
|
819
|
+
function cloneAttributes(mergeTo, mergeFrom) {
|
|
820
|
+
forEach(mergeTo.attributes, function(attr) {
|
|
754
821
|
if (!mergeFrom.hasAttribute(attr.name) && shouldSettleAttribute(attr.name)) {
|
|
755
822
|
mergeTo.removeAttribute(attr.name)
|
|
756
823
|
}
|
|
757
824
|
})
|
|
758
|
-
forEach(mergeFrom.attributes, function
|
|
825
|
+
forEach(mergeFrom.attributes, function(attr) {
|
|
759
826
|
if (shouldSettleAttribute(attr.name)) {
|
|
760
827
|
mergeTo.setAttribute(attr.name, attr.value)
|
|
761
828
|
}
|
|
762
829
|
})
|
|
763
830
|
}
|
|
764
831
|
|
|
765
|
-
function isInlineSwap
|
|
832
|
+
function isInlineSwap(swapStyle, target) {
|
|
766
833
|
const extensions = getExtensions(target)
|
|
767
834
|
for (let i = 0; i < extensions.length; i++) {
|
|
768
835
|
const extension = extensions[i]
|
|
@@ -780,11 +847,11 @@ const htmx = (function () {
|
|
|
780
847
|
/**
|
|
781
848
|
*
|
|
782
849
|
* @param {string} oobValue
|
|
783
|
-
* @param {
|
|
850
|
+
* @param {Element} oobElement
|
|
784
851
|
* @param {*} settleInfo
|
|
785
852
|
* @returns
|
|
786
853
|
*/
|
|
787
|
-
function oobSwap
|
|
854
|
+
function oobSwap(oobValue, oobElement, settleInfo) {
|
|
788
855
|
let selector = '#' + getRawAttribute(oobElement, 'id')
|
|
789
856
|
let swapStyle = 'outerHTML'
|
|
790
857
|
if (oobValue === 'true') {
|
|
@@ -800,7 +867,7 @@ const htmx = (function () {
|
|
|
800
867
|
if (targets) {
|
|
801
868
|
forEach(
|
|
802
869
|
targets,
|
|
803
|
-
function
|
|
870
|
+
function(target) {
|
|
804
871
|
let fragment
|
|
805
872
|
const oobElementClone = oobElement.cloneNode(true)
|
|
806
873
|
fragment = getDocument().createDocumentFragment()
|
|
@@ -814,9 +881,9 @@ const htmx = (function () {
|
|
|
814
881
|
|
|
815
882
|
target = beforeSwapDetails.target // allow re-targeting
|
|
816
883
|
if (beforeSwapDetails.shouldSwap) {
|
|
817
|
-
|
|
884
|
+
swapWithStyle(swapStyle, target, target, fragment, settleInfo)
|
|
818
885
|
}
|
|
819
|
-
forEach(settleInfo.elts, function
|
|
886
|
+
forEach(settleInfo.elts, function(elt) {
|
|
820
887
|
triggerEvent(elt, 'htmx:oobAfterSwap', beforeSwapDetails)
|
|
821
888
|
})
|
|
822
889
|
}
|
|
@@ -829,33 +896,8 @@ const htmx = (function () {
|
|
|
829
896
|
return oobValue
|
|
830
897
|
}
|
|
831
898
|
|
|
832
|
-
function
|
|
833
|
-
|
|
834
|
-
if (oobSelects) {
|
|
835
|
-
const oobSelectValues = oobSelects.split(',')
|
|
836
|
-
for (let i = 0; i < oobSelectValues.length; i++) {
|
|
837
|
-
const oobSelectValue = oobSelectValues[i].split(':', 2)
|
|
838
|
-
let id = oobSelectValue[0].trim()
|
|
839
|
-
if (id.indexOf('#') === 0) {
|
|
840
|
-
id = id.substring(1)
|
|
841
|
-
}
|
|
842
|
-
const oobValue = oobSelectValue[1] || 'true'
|
|
843
|
-
const oobElement = fragment.querySelector('#' + id)
|
|
844
|
-
if (oobElement) {
|
|
845
|
-
oobSwap(oobValue, oobElement, settleInfo)
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
forEach(findAll(fragment, '[hx-swap-oob], [data-hx-swap-oob]'), function (oobElement) {
|
|
850
|
-
const oobValue = getAttributeValue(oobElement, 'hx-swap-oob')
|
|
851
|
-
if (oobValue != null) {
|
|
852
|
-
oobSwap(oobValue, oobElement, settleInfo)
|
|
853
|
-
}
|
|
854
|
-
})
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
function handlePreservedElements (fragment) {
|
|
858
|
-
forEach(findAll(fragment, '[hx-preserve], [data-hx-preserve]'), function (preservedElt) {
|
|
899
|
+
function handlePreservedElements(fragment) {
|
|
900
|
+
forEach(findAll(fragment, '[hx-preserve], [data-hx-preserve]'), function(preservedElt) {
|
|
859
901
|
const id = getAttributeValue(preservedElt, 'id')
|
|
860
902
|
const oldElt = getDocument().getElementById(id)
|
|
861
903
|
if (oldElt != null) {
|
|
@@ -864,8 +906,8 @@ const htmx = (function () {
|
|
|
864
906
|
})
|
|
865
907
|
}
|
|
866
908
|
|
|
867
|
-
function handleAttributes
|
|
868
|
-
forEach(fragment.querySelectorAll('[id]'), function
|
|
909
|
+
function handleAttributes(parentNode, fragment, settleInfo) {
|
|
910
|
+
forEach(fragment.querySelectorAll('[id]'), function(newNode) {
|
|
869
911
|
const id = getRawAttribute(newNode, 'id')
|
|
870
912
|
if (id && id.length > 0) {
|
|
871
913
|
const normalizedId = id.replace("'", "\\'")
|
|
@@ -874,7 +916,7 @@ const htmx = (function () {
|
|
|
874
916
|
if (oldNode && oldNode !== parentNode) {
|
|
875
917
|
const newAttributes = newNode.cloneNode()
|
|
876
918
|
cloneAttributes(newNode, oldNode)
|
|
877
|
-
settleInfo.tasks.push(function
|
|
919
|
+
settleInfo.tasks.push(function() {
|
|
878
920
|
cloneAttributes(newNode, newAttributes)
|
|
879
921
|
})
|
|
880
922
|
}
|
|
@@ -882,17 +924,16 @@ const htmx = (function () {
|
|
|
882
924
|
})
|
|
883
925
|
}
|
|
884
926
|
|
|
885
|
-
function makeAjaxLoadTask
|
|
886
|
-
return function
|
|
927
|
+
function makeAjaxLoadTask(child) {
|
|
928
|
+
return function() {
|
|
887
929
|
removeClassFromElement(child, htmx.config.addedClass)
|
|
888
930
|
processNode(child)
|
|
889
|
-
processScripts(child)
|
|
890
931
|
processFocus(child)
|
|
891
932
|
triggerEvent(child, 'htmx:load')
|
|
892
933
|
}
|
|
893
934
|
}
|
|
894
935
|
|
|
895
|
-
function processFocus
|
|
936
|
+
function processFocus(child) {
|
|
896
937
|
const autofocus = '[autofocus]'
|
|
897
938
|
const autoFocusedElt = matches(child, autofocus) ? child : child.querySelector(autofocus)
|
|
898
939
|
if (autoFocusedElt != null) {
|
|
@@ -900,7 +941,7 @@ const htmx = (function () {
|
|
|
900
941
|
}
|
|
901
942
|
}
|
|
902
943
|
|
|
903
|
-
function insertNodesBefore
|
|
944
|
+
function insertNodesBefore(parentNode, insertBefore, fragment, settleInfo) {
|
|
904
945
|
handleAttributes(parentNode, fragment, settleInfo)
|
|
905
946
|
while (fragment.childNodes.length > 0) {
|
|
906
947
|
const child = fragment.firstChild
|
|
@@ -914,7 +955,7 @@ const htmx = (function () {
|
|
|
914
955
|
|
|
915
956
|
// based on https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0,
|
|
916
957
|
// derived from Java's string hashcode implementation
|
|
917
|
-
function stringHash
|
|
958
|
+
function stringHash(string, hash) {
|
|
918
959
|
let char = 0
|
|
919
960
|
while (char < string.length) {
|
|
920
961
|
hash = (hash << 5) - hash + string.charCodeAt(char++) | 0 // bitwise or ensures we have a 32-bit int
|
|
@@ -922,7 +963,7 @@ const htmx = (function () {
|
|
|
922
963
|
return hash
|
|
923
964
|
}
|
|
924
965
|
|
|
925
|
-
function attributeHash
|
|
966
|
+
function attributeHash(elt) {
|
|
926
967
|
let hash = 0
|
|
927
968
|
// IE fix
|
|
928
969
|
if (elt.attributes) {
|
|
@@ -937,7 +978,7 @@ const htmx = (function () {
|
|
|
937
978
|
return hash
|
|
938
979
|
}
|
|
939
980
|
|
|
940
|
-
function deInitOnHandlers
|
|
981
|
+
function deInitOnHandlers(elt) {
|
|
941
982
|
const internalData = getInternalData(elt)
|
|
942
983
|
if (internalData.onHandlers) {
|
|
943
984
|
for (let i = 0; i < internalData.onHandlers.length; i++) {
|
|
@@ -948,76 +989,72 @@ const htmx = (function () {
|
|
|
948
989
|
}
|
|
949
990
|
}
|
|
950
991
|
|
|
951
|
-
function deInitNode
|
|
992
|
+
function deInitNode(element) {
|
|
952
993
|
const internalData = getInternalData(element)
|
|
953
994
|
if (internalData.timeout) {
|
|
954
995
|
clearTimeout(internalData.timeout)
|
|
955
996
|
}
|
|
956
997
|
if (internalData.listenerInfos) {
|
|
957
|
-
forEach(internalData.listenerInfos, function
|
|
998
|
+
forEach(internalData.listenerInfos, function(info) {
|
|
958
999
|
if (info.on) {
|
|
959
1000
|
info.on.removeEventListener(info.trigger, info.listener)
|
|
960
1001
|
}
|
|
961
1002
|
})
|
|
962
1003
|
}
|
|
963
1004
|
deInitOnHandlers(element)
|
|
964
|
-
forEach(Object.keys(internalData), function
|
|
1005
|
+
forEach(Object.keys(internalData), function(key) { delete internalData[key] })
|
|
965
1006
|
}
|
|
966
1007
|
|
|
967
|
-
function cleanUpElement
|
|
1008
|
+
function cleanUpElement(element) {
|
|
968
1009
|
triggerEvent(element, 'htmx:beforeCleanupElement')
|
|
969
1010
|
deInitNode(element)
|
|
970
1011
|
if (element.children) { // IE
|
|
971
|
-
forEach(element.children, function
|
|
1012
|
+
forEach(element.children, function(child) { cleanUpElement(child) })
|
|
972
1013
|
}
|
|
973
1014
|
}
|
|
974
1015
|
|
|
975
|
-
function swapOuterHTML
|
|
976
|
-
|
|
977
|
-
|
|
1016
|
+
function swapOuterHTML(target, fragment, settleInfo) {
|
|
1017
|
+
// @type {HTMLElement}
|
|
1018
|
+
let newElt
|
|
1019
|
+
const eltBeforeNewContent = target.previousSibling
|
|
1020
|
+
insertNodesBefore(parentElt(target), target, fragment, settleInfo)
|
|
1021
|
+
if (eltBeforeNewContent == null) {
|
|
1022
|
+
newElt = parentElt(target).firstChild
|
|
978
1023
|
} else {
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
if (
|
|
984
|
-
newElt
|
|
985
|
-
} else {
|
|
986
|
-
newElt = eltBeforeNewContent.nextSibling
|
|
987
|
-
}
|
|
988
|
-
settleInfo.elts = settleInfo.elts.filter(function (e) { return e != target })
|
|
989
|
-
while (newElt && newElt !== target) {
|
|
990
|
-
if (newElt.nodeType === Node.ELEMENT_NODE) {
|
|
991
|
-
settleInfo.elts.push(newElt)
|
|
992
|
-
}
|
|
993
|
-
newElt = newElt.nextElementSibling
|
|
1024
|
+
newElt = eltBeforeNewContent.nextSibling
|
|
1025
|
+
}
|
|
1026
|
+
settleInfo.elts = settleInfo.elts.filter(function(e) { return e !== target })
|
|
1027
|
+
while (newElt && newElt !== target) {
|
|
1028
|
+
if (newElt.nodeType === Node.ELEMENT_NODE) {
|
|
1029
|
+
settleInfo.elts.push(newElt)
|
|
994
1030
|
}
|
|
995
|
-
|
|
996
|
-
parentElt(target).removeChild(target)
|
|
1031
|
+
newElt = newElt.nextElementSibling
|
|
997
1032
|
}
|
|
1033
|
+
cleanUpElement(target)
|
|
1034
|
+
target.remove()
|
|
998
1035
|
}
|
|
999
1036
|
|
|
1000
|
-
function swapAfterBegin
|
|
1037
|
+
function swapAfterBegin(target, fragment, settleInfo) {
|
|
1001
1038
|
return insertNodesBefore(target, target.firstChild, fragment, settleInfo)
|
|
1002
1039
|
}
|
|
1003
1040
|
|
|
1004
|
-
function swapBeforeBegin
|
|
1041
|
+
function swapBeforeBegin(target, fragment, settleInfo) {
|
|
1005
1042
|
return insertNodesBefore(parentElt(target), target, fragment, settleInfo)
|
|
1006
1043
|
}
|
|
1007
1044
|
|
|
1008
|
-
function swapBeforeEnd
|
|
1045
|
+
function swapBeforeEnd(target, fragment, settleInfo) {
|
|
1009
1046
|
return insertNodesBefore(target, null, fragment, settleInfo)
|
|
1010
1047
|
}
|
|
1011
1048
|
|
|
1012
|
-
function swapAfterEnd
|
|
1049
|
+
function swapAfterEnd(target, fragment, settleInfo) {
|
|
1013
1050
|
return insertNodesBefore(parentElt(target), target.nextSibling, fragment, settleInfo)
|
|
1014
1051
|
}
|
|
1015
|
-
function swapDelete
|
|
1052
|
+
function swapDelete(target, fragment, settleInfo) {
|
|
1016
1053
|
cleanUpElement(target)
|
|
1017
1054
|
return parentElt(target).removeChild(target)
|
|
1018
1055
|
}
|
|
1019
1056
|
|
|
1020
|
-
function swapInnerHTML
|
|
1057
|
+
function swapInnerHTML(target, fragment, settleInfo) {
|
|
1021
1058
|
const firstChild = target.firstChild
|
|
1022
1059
|
insertNodesBefore(target, firstChild, fragment, settleInfo)
|
|
1023
1060
|
if (firstChild) {
|
|
@@ -1030,19 +1067,14 @@ const htmx = (function () {
|
|
|
1030
1067
|
}
|
|
1031
1068
|
}
|
|
1032
1069
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
}
|
|
1042
|
-
return fragment
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
function swap (swapStyle, elt, target, fragment, settleInfo) {
|
|
1070
|
+
/**
|
|
1071
|
+
* @param {string} swapStyle
|
|
1072
|
+
* @param {HTMLElement} elt
|
|
1073
|
+
* @param {HTMLElement} target
|
|
1074
|
+
* @param {Node} fragment
|
|
1075
|
+
* @param {{ tasks: (() => void)[]; }} settleInfo
|
|
1076
|
+
*/
|
|
1077
|
+
function swapWithStyle(swapStyle, elt, target, fragment, settleInfo) {
|
|
1046
1078
|
switch (swapStyle) {
|
|
1047
1079
|
case 'none':
|
|
1048
1080
|
return
|
|
@@ -1089,33 +1121,176 @@ const htmx = (function () {
|
|
|
1089
1121
|
if (swapStyle === 'innerHTML') {
|
|
1090
1122
|
swapInnerHTML(target, fragment, settleInfo)
|
|
1091
1123
|
} else {
|
|
1092
|
-
|
|
1124
|
+
swapWithStyle(htmx.config.defaultSwapStyle, elt, target, fragment, settleInfo)
|
|
1093
1125
|
}
|
|
1094
1126
|
}
|
|
1095
1127
|
}
|
|
1096
1128
|
|
|
1097
|
-
function
|
|
1098
|
-
|
|
1099
|
-
const
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
return result[2]
|
|
1129
|
+
function findAndSwapOobElements(fragment, settleInfo) {
|
|
1130
|
+
forEach(findAll(fragment, '[hx-swap-oob], [data-hx-swap-oob]'), function(oobElement) {
|
|
1131
|
+
const oobValue = getAttributeValue(oobElement, 'hx-swap-oob')
|
|
1132
|
+
if (oobValue != null) {
|
|
1133
|
+
oobSwap(oobValue, oobElement, settleInfo)
|
|
1103
1134
|
}
|
|
1104
|
-
}
|
|
1135
|
+
})
|
|
1105
1136
|
}
|
|
1106
1137
|
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1138
|
+
/**
|
|
1139
|
+
* @callback swapCallback
|
|
1140
|
+
*/
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* @typedef {Object} SwapOptions
|
|
1144
|
+
* @property {?string} select
|
|
1145
|
+
* @property {?string} selectOOB
|
|
1146
|
+
* @property {?*} eventInfo
|
|
1147
|
+
* @property {?*} anchor
|
|
1148
|
+
* @property {?HTMLElement} contextElement
|
|
1149
|
+
* @property {?swapCallback} afterSwapCallback
|
|
1150
|
+
* @property {?swapCallback} afterSettleCallback
|
|
1151
|
+
*/
|
|
1152
|
+
|
|
1153
|
+
/**
|
|
1154
|
+
* Implements complete swapping pipeline, including: focus and selection preservation,
|
|
1155
|
+
* title updates, scroll, OOB swapping, normal swapping and settling
|
|
1156
|
+
* @param {string|Element} target
|
|
1157
|
+
* @param {string} content
|
|
1158
|
+
* @param {import("./htmx").HtmxSwapSpecification} swapSpec
|
|
1159
|
+
* @param {SwapOptions} swapOptions
|
|
1160
|
+
*/
|
|
1161
|
+
function swap(target, content, swapSpec, swapOptions) {
|
|
1162
|
+
if (!swapOptions) {
|
|
1163
|
+
swapOptions = {}
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
target = resolveTarget(target)
|
|
1167
|
+
|
|
1168
|
+
// preserve focus and selection
|
|
1169
|
+
const activeElt = document.activeElement
|
|
1170
|
+
let selectionInfo = {}
|
|
1171
|
+
try {
|
|
1172
|
+
selectionInfo = {
|
|
1173
|
+
elt: activeElt,
|
|
1174
|
+
// @ts-ignore
|
|
1175
|
+
start: activeElt ? activeElt.selectionStart : null,
|
|
1176
|
+
// @ts-ignore
|
|
1177
|
+
end: activeElt ? activeElt.selectionEnd : null
|
|
1178
|
+
}
|
|
1179
|
+
} catch (e) {
|
|
1180
|
+
// safari issue - see https://github.com/microsoft/playwright/issues/5894
|
|
1181
|
+
}
|
|
1182
|
+
const settleInfo = makeSettleInfo(target)
|
|
1183
|
+
|
|
1184
|
+
let fragment = makeFragment(content)
|
|
1185
|
+
|
|
1186
|
+
settleInfo.title = fragment.title
|
|
1187
|
+
|
|
1188
|
+
// select-oob swaps
|
|
1189
|
+
if (swapOptions.selectOOB) {
|
|
1190
|
+
const oobSelectValues = swapOptions.selectOOB.split(',')
|
|
1191
|
+
for (let i = 0; i < oobSelectValues.length; i++) {
|
|
1192
|
+
const oobSelectValue = oobSelectValues[i].split(':', 2)
|
|
1193
|
+
let id = oobSelectValue[0].trim()
|
|
1194
|
+
if (id.indexOf('#') === 0) {
|
|
1195
|
+
id = id.substring(1)
|
|
1196
|
+
}
|
|
1197
|
+
const oobValue = oobSelectValue[1] || 'true'
|
|
1198
|
+
const oobElement = fragment.querySelector('#' + id)
|
|
1199
|
+
if (oobElement) {
|
|
1200
|
+
oobSwap(oobValue, oobElement, settleInfo)
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
// oob swaps
|
|
1205
|
+
findAndSwapOobElements(fragment, settleInfo)
|
|
1206
|
+
forEach(findAll(fragment, 'template'), function(template) {
|
|
1207
|
+
findAndSwapOobElements(template.content, settleInfo)
|
|
1208
|
+
if (template.content.childElementCount === 0) {
|
|
1209
|
+
// Avoid polluting the DOM with empty templates that were only used to encapsulate oob swap
|
|
1210
|
+
template.remove()
|
|
1211
|
+
}
|
|
1212
|
+
})
|
|
1213
|
+
|
|
1214
|
+
// normal swap
|
|
1215
|
+
if (swapOptions.select) {
|
|
1216
|
+
const newFragment = getDocument().createDocumentFragment()
|
|
1217
|
+
forEach(fragment.querySelectorAll(swapOptions.select), function(node) {
|
|
1218
|
+
newFragment.appendChild(node)
|
|
1219
|
+
})
|
|
1220
|
+
fragment = newFragment
|
|
1221
|
+
}
|
|
1222
|
+
handlePreservedElements(fragment)
|
|
1223
|
+
swapWithStyle(swapSpec.swapStyle, swapOptions.contextElement, target, fragment, settleInfo)
|
|
1224
|
+
|
|
1225
|
+
// apply saved focus and selection information to swapped content
|
|
1226
|
+
if (selectionInfo.elt &&
|
|
1227
|
+
!bodyContains(selectionInfo.elt) &&
|
|
1228
|
+
getRawAttribute(selectionInfo.elt, 'id')) {
|
|
1229
|
+
const newActiveElt = document.getElementById(getRawAttribute(selectionInfo.elt, 'id'))
|
|
1230
|
+
const focusOptions = { preventScroll: swapSpec.focusScroll !== undefined ? !swapSpec.focusScroll : !htmx.config.defaultFocusScroll }
|
|
1231
|
+
if (newActiveElt) {
|
|
1232
|
+
// @ts-ignore
|
|
1233
|
+
if (selectionInfo.start && newActiveElt.setSelectionRange) {
|
|
1234
|
+
try {
|
|
1235
|
+
// @ts-ignore
|
|
1236
|
+
newActiveElt.setSelectionRange(selectionInfo.start, selectionInfo.end)
|
|
1237
|
+
} catch (e) {
|
|
1238
|
+
// the setSelectionRange method is present on fields that don't support it, so just let this fail
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
newActiveElt.focus(focusOptions)
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
target.classList.remove(htmx.config.swappingClass)
|
|
1246
|
+
forEach(settleInfo.elts, function(elt) {
|
|
1247
|
+
if (elt.classList) {
|
|
1248
|
+
elt.classList.add(htmx.config.settlingClass)
|
|
1249
|
+
}
|
|
1250
|
+
triggerEvent(elt, 'htmx:afterSwap', swapOptions.eventInfo)
|
|
1251
|
+
})
|
|
1252
|
+
if (swapOptions.afterSwapCallback) {
|
|
1253
|
+
swapOptions.afterSwapCallback()
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
// merge in new title after swap but before settle
|
|
1257
|
+
if (!swapSpec.ignoreTitle) {
|
|
1258
|
+
handleTitle(settleInfo.title)
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
// settle
|
|
1262
|
+
const doSettle = function() {
|
|
1263
|
+
forEach(settleInfo.tasks, function(task) {
|
|
1264
|
+
task.call()
|
|
1265
|
+
})
|
|
1266
|
+
forEach(settleInfo.elts, function(elt) {
|
|
1267
|
+
if (elt.classList) {
|
|
1268
|
+
elt.classList.remove(htmx.config.settlingClass)
|
|
1269
|
+
}
|
|
1270
|
+
triggerEvent(elt, 'htmx:afterSettle', swapOptions.eventInfo)
|
|
1271
|
+
})
|
|
1272
|
+
|
|
1273
|
+
if (swapOptions.anchor) {
|
|
1274
|
+
const anchorTarget = resolveTarget('#' + swapOptions.anchor)
|
|
1275
|
+
if (anchorTarget) {
|
|
1276
|
+
anchorTarget.scrollIntoView({ block: 'start', behavior: 'auto' })
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
updateScrollState(settleInfo.elts, swapSpec)
|
|
1281
|
+
if (swapOptions.afterSettleCallback) {
|
|
1282
|
+
swapOptions.afterSettleCallback()
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
if (swapSpec.settleDelay > 0) {
|
|
1287
|
+
setTimeout(doSettle, swapSpec.settleDelay)
|
|
1288
|
+
} else {
|
|
1289
|
+
doSettle()
|
|
1115
1290
|
}
|
|
1116
1291
|
}
|
|
1117
1292
|
|
|
1118
|
-
function
|
|
1293
|
+
function handleTriggerHeader(xhr, header, elt) {
|
|
1119
1294
|
const triggerBody = xhr.getResponseHeader(header)
|
|
1120
1295
|
if (triggerBody.indexOf('{') === 0) {
|
|
1121
1296
|
const triggers = parseJSON(triggerBody)
|
|
@@ -1144,7 +1319,7 @@ const htmx = (function () {
|
|
|
1144
1319
|
const NOT_WHITESPACE = /[^\s]/
|
|
1145
1320
|
const COMBINED_SELECTOR_START = /[{(]/
|
|
1146
1321
|
const COMBINED_SELECTOR_END = /[})]/
|
|
1147
|
-
function tokenizeString
|
|
1322
|
+
function tokenizeString(str) {
|
|
1148
1323
|
const tokens = []
|
|
1149
1324
|
let position = 0
|
|
1150
1325
|
while (position < str.length) {
|
|
@@ -1174,7 +1349,7 @@ const htmx = (function () {
|
|
|
1174
1349
|
return tokens
|
|
1175
1350
|
}
|
|
1176
1351
|
|
|
1177
|
-
function isPossibleRelativeReference
|
|
1352
|
+
function isPossibleRelativeReference(token, last, paramName) {
|
|
1178
1353
|
return SYMBOL_START.exec(token.charAt(0)) &&
|
|
1179
1354
|
token !== 'true' &&
|
|
1180
1355
|
token !== 'false' &&
|
|
@@ -1183,7 +1358,7 @@ const htmx = (function () {
|
|
|
1183
1358
|
last !== '.'
|
|
1184
1359
|
}
|
|
1185
1360
|
|
|
1186
|
-
function maybeGenerateConditional
|
|
1361
|
+
function maybeGenerateConditional(elt, tokens, paramName) {
|
|
1187
1362
|
if (tokens[0] === '[') {
|
|
1188
1363
|
tokens.shift()
|
|
1189
1364
|
let bracketCount = 1
|
|
@@ -1200,10 +1375,10 @@ const htmx = (function () {
|
|
|
1200
1375
|
tokens.shift()
|
|
1201
1376
|
conditionalSource += ')})'
|
|
1202
1377
|
try {
|
|
1203
|
-
const conditionFunction = maybeEval(elt, function
|
|
1378
|
+
const conditionFunction = maybeEval(elt, function() {
|
|
1204
1379
|
return Function(conditionalSource)()
|
|
1205
1380
|
},
|
|
1206
|
-
function
|
|
1381
|
+
function() { return true })
|
|
1207
1382
|
conditionFunction.source = conditionalSource
|
|
1208
1383
|
return conditionFunction
|
|
1209
1384
|
} catch (e) {
|
|
@@ -1224,7 +1399,7 @@ const htmx = (function () {
|
|
|
1224
1399
|
}
|
|
1225
1400
|
}
|
|
1226
1401
|
|
|
1227
|
-
function consumeUntil
|
|
1402
|
+
function consumeUntil(tokens, match) {
|
|
1228
1403
|
let result = ''
|
|
1229
1404
|
while (tokens.length > 0 && !match.test(tokens[0])) {
|
|
1230
1405
|
result += tokens.shift()
|
|
@@ -1232,7 +1407,7 @@ const htmx = (function () {
|
|
|
1232
1407
|
return result
|
|
1233
1408
|
}
|
|
1234
1409
|
|
|
1235
|
-
function consumeCSSSelector
|
|
1410
|
+
function consumeCSSSelector(tokens) {
|
|
1236
1411
|
let result
|
|
1237
1412
|
if (tokens.length > 0 && COMBINED_SELECTOR_START.test(tokens[0])) {
|
|
1238
1413
|
tokens.shift()
|
|
@@ -1252,7 +1427,7 @@ const htmx = (function () {
|
|
|
1252
1427
|
* @param {cache} cache for trigger specs
|
|
1253
1428
|
* @returns {import("./htmx").HtmxTriggerSpecification[]}
|
|
1254
1429
|
*/
|
|
1255
|
-
function parseAndCacheTrigger
|
|
1430
|
+
function parseAndCacheTrigger(elt, explicitTrigger, cache) {
|
|
1256
1431
|
const triggerSpecs = []
|
|
1257
1432
|
const tokens = tokenizeString(explicitTrigger)
|
|
1258
1433
|
do {
|
|
@@ -1341,7 +1516,7 @@ const htmx = (function () {
|
|
|
1341
1516
|
* @param {HTMLElement} elt
|
|
1342
1517
|
* @returns {import("./htmx").HtmxTriggerSpecification[]}
|
|
1343
1518
|
*/
|
|
1344
|
-
function getTriggerSpecs
|
|
1519
|
+
function getTriggerSpecs(elt) {
|
|
1345
1520
|
const explicitTrigger = getAttributeValue(elt, 'hx-trigger')
|
|
1346
1521
|
let triggerSpecs = []
|
|
1347
1522
|
if (explicitTrigger) {
|
|
@@ -1362,13 +1537,13 @@ const htmx = (function () {
|
|
|
1362
1537
|
}
|
|
1363
1538
|
}
|
|
1364
1539
|
|
|
1365
|
-
function cancelPolling
|
|
1540
|
+
function cancelPolling(elt) {
|
|
1366
1541
|
getInternalData(elt).cancelled = true
|
|
1367
1542
|
}
|
|
1368
1543
|
|
|
1369
|
-
function processPolling
|
|
1544
|
+
function processPolling(elt, handler, spec) {
|
|
1370
1545
|
const nodeData = getInternalData(elt)
|
|
1371
|
-
nodeData.timeout = setTimeout(function
|
|
1546
|
+
nodeData.timeout = setTimeout(function() {
|
|
1372
1547
|
if (bodyContains(elt) && nodeData.cancelled !== true) {
|
|
1373
1548
|
if (!maybeFilterEvent(spec, elt, makeEvent('hx:poll:trigger', {
|
|
1374
1549
|
triggerSpec: spec,
|
|
@@ -1381,13 +1556,13 @@ const htmx = (function () {
|
|
|
1381
1556
|
}, spec.pollInterval)
|
|
1382
1557
|
}
|
|
1383
1558
|
|
|
1384
|
-
function isLocalLink
|
|
1559
|
+
function isLocalLink(elt) {
|
|
1385
1560
|
return location.hostname === elt.hostname &&
|
|
1386
1561
|
getRawAttribute(elt, 'href') &&
|
|
1387
1562
|
getRawAttribute(elt, 'href').indexOf('#') !== 0
|
|
1388
1563
|
}
|
|
1389
1564
|
|
|
1390
|
-
function boostElement
|
|
1565
|
+
function boostElement(elt, nodeData, triggerSpecs) {
|
|
1391
1566
|
if ((elt.tagName === 'A' && isLocalLink(elt) && (elt.target === '' || elt.target === '_self')) || elt.tagName === 'FORM') {
|
|
1392
1567
|
nodeData.boosted = true
|
|
1393
1568
|
let verb, path
|
|
@@ -1401,8 +1576,8 @@ const htmx = (function () {
|
|
|
1401
1576
|
}
|
|
1402
1577
|
path = getRawAttribute(elt, 'action')
|
|
1403
1578
|
}
|
|
1404
|
-
triggerSpecs.forEach(function
|
|
1405
|
-
addEventListener(elt, function
|
|
1579
|
+
triggerSpecs.forEach(function(triggerSpec) {
|
|
1580
|
+
addEventListener(elt, function(elt, evt) {
|
|
1406
1581
|
if (closest(elt, htmx.config.disableSelector)) {
|
|
1407
1582
|
cleanUpElement(elt)
|
|
1408
1583
|
return
|
|
@@ -1419,7 +1594,7 @@ const htmx = (function () {
|
|
|
1419
1594
|
* @param {HTMLElement} elt
|
|
1420
1595
|
* @returns
|
|
1421
1596
|
*/
|
|
1422
|
-
function shouldCancel
|
|
1597
|
+
function shouldCancel(evt, elt) {
|
|
1423
1598
|
if (evt.type === 'submit' || evt.type === 'click') {
|
|
1424
1599
|
if (elt.tagName === 'FORM') {
|
|
1425
1600
|
return true
|
|
@@ -1435,11 +1610,11 @@ const htmx = (function () {
|
|
|
1435
1610
|
return false
|
|
1436
1611
|
}
|
|
1437
1612
|
|
|
1438
|
-
function ignoreBoostedAnchorCtrlClick
|
|
1613
|
+
function ignoreBoostedAnchorCtrlClick(elt, evt) {
|
|
1439
1614
|
return getInternalData(elt).boosted && elt.tagName === 'A' && evt.type === 'click' && (evt.ctrlKey || evt.metaKey)
|
|
1440
1615
|
}
|
|
1441
1616
|
|
|
1442
|
-
function maybeFilterEvent
|
|
1617
|
+
function maybeFilterEvent(triggerSpec, elt, evt) {
|
|
1443
1618
|
const eventFilter = triggerSpec.eventFilter
|
|
1444
1619
|
if (eventFilter) {
|
|
1445
1620
|
try {
|
|
@@ -1452,7 +1627,7 @@ const htmx = (function () {
|
|
|
1452
1627
|
return false
|
|
1453
1628
|
}
|
|
1454
1629
|
|
|
1455
|
-
function addEventListener
|
|
1630
|
+
function addEventListener(elt, handler, nodeData, triggerSpec, explicitCancel) {
|
|
1456
1631
|
const elementData = getInternalData(elt)
|
|
1457
1632
|
let eltsToListenOn
|
|
1458
1633
|
if (triggerSpec.from) {
|
|
@@ -1462,13 +1637,13 @@ const htmx = (function () {
|
|
|
1462
1637
|
}
|
|
1463
1638
|
// store the initial values of the elements, so we can tell if they change
|
|
1464
1639
|
if (triggerSpec.changed) {
|
|
1465
|
-
eltsToListenOn.forEach(function
|
|
1640
|
+
eltsToListenOn.forEach(function(eltToListenOn) {
|
|
1466
1641
|
const eltToListenOnData = getInternalData(eltToListenOn)
|
|
1467
1642
|
eltToListenOnData.lastValue = eltToListenOn.value
|
|
1468
1643
|
})
|
|
1469
1644
|
}
|
|
1470
|
-
forEach(eltsToListenOn, function
|
|
1471
|
-
const eventListener = function
|
|
1645
|
+
forEach(eltsToListenOn, function(eltToListenOn) {
|
|
1646
|
+
const eventListener = function(evt) {
|
|
1472
1647
|
if (!bodyContains(elt)) {
|
|
1473
1648
|
eltToListenOn.removeEventListener(triggerSpec.trigger, eventListener)
|
|
1474
1649
|
return
|
|
@@ -1521,12 +1696,12 @@ const htmx = (function () {
|
|
|
1521
1696
|
if (triggerSpec.throttle > 0) {
|
|
1522
1697
|
if (!elementData.throttle) {
|
|
1523
1698
|
handler(elt, evt)
|
|
1524
|
-
elementData.throttle = setTimeout(function
|
|
1699
|
+
elementData.throttle = setTimeout(function() {
|
|
1525
1700
|
elementData.throttle = null
|
|
1526
1701
|
}, triggerSpec.throttle)
|
|
1527
1702
|
}
|
|
1528
1703
|
} else if (triggerSpec.delay > 0) {
|
|
1529
|
-
elementData.delayed = setTimeout(function
|
|
1704
|
+
elementData.delayed = setTimeout(function() { handler(elt, evt) }, triggerSpec.delay)
|
|
1530
1705
|
} else {
|
|
1531
1706
|
triggerEvent(elt, 'htmx:trigger')
|
|
1532
1707
|
handler(elt, evt)
|
|
@@ -1547,16 +1722,16 @@ const htmx = (function () {
|
|
|
1547
1722
|
|
|
1548
1723
|
let windowIsScrolling = false // used by initScrollHandler
|
|
1549
1724
|
let scrollHandler = null
|
|
1550
|
-
function initScrollHandler
|
|
1725
|
+
function initScrollHandler() {
|
|
1551
1726
|
if (!scrollHandler) {
|
|
1552
|
-
scrollHandler = function
|
|
1727
|
+
scrollHandler = function() {
|
|
1553
1728
|
windowIsScrolling = true
|
|
1554
1729
|
}
|
|
1555
1730
|
window.addEventListener('scroll', scrollHandler)
|
|
1556
|
-
setInterval(function
|
|
1731
|
+
setInterval(function() {
|
|
1557
1732
|
if (windowIsScrolling) {
|
|
1558
1733
|
windowIsScrolling = false
|
|
1559
|
-
forEach(getDocument().querySelectorAll("[hx-trigger
|
|
1734
|
+
forEach(getDocument().querySelectorAll("[hx-trigger*='revealed'],[data-hx-trigger*='revealed']"), function(elt) {
|
|
1560
1735
|
maybeReveal(elt)
|
|
1561
1736
|
})
|
|
1562
1737
|
}
|
|
@@ -1564,7 +1739,7 @@ const htmx = (function () {
|
|
|
1564
1739
|
}
|
|
1565
1740
|
}
|
|
1566
1741
|
|
|
1567
|
-
function maybeReveal
|
|
1742
|
+
function maybeReveal(elt) {
|
|
1568
1743
|
if (!hasAttribute(elt, 'data-hx-revealed') && isScrolledIntoView(elt)) {
|
|
1569
1744
|
elt.setAttribute('data-hx-revealed', 'true')
|
|
1570
1745
|
const nodeData = getInternalData(elt)
|
|
@@ -1572,15 +1747,15 @@ const htmx = (function () {
|
|
|
1572
1747
|
triggerEvent(elt, 'revealed')
|
|
1573
1748
|
} else {
|
|
1574
1749
|
// if the node isn't initialized, wait for it before triggering the request
|
|
1575
|
-
elt.addEventListener('htmx:afterProcessNode', function
|
|
1750
|
+
elt.addEventListener('htmx:afterProcessNode', function(evt) { triggerEvent(elt, 'revealed') }, { once: true })
|
|
1576
1751
|
}
|
|
1577
1752
|
}
|
|
1578
1753
|
}
|
|
1579
1754
|
|
|
1580
1755
|
//= ===================================================================
|
|
1581
1756
|
|
|
1582
|
-
function loadImmediately
|
|
1583
|
-
const load = function
|
|
1757
|
+
function loadImmediately(elt, handler, nodeData, delay) {
|
|
1758
|
+
const load = function() {
|
|
1584
1759
|
if (!nodeData.loaded) {
|
|
1585
1760
|
nodeData.loaded = true
|
|
1586
1761
|
handler(elt)
|
|
@@ -1593,16 +1768,16 @@ const htmx = (function () {
|
|
|
1593
1768
|
}
|
|
1594
1769
|
}
|
|
1595
1770
|
|
|
1596
|
-
function processVerbs
|
|
1771
|
+
function processVerbs(elt, nodeData, triggerSpecs) {
|
|
1597
1772
|
let explicitAction = false
|
|
1598
|
-
forEach(VERBS, function
|
|
1773
|
+
forEach(VERBS, function(verb) {
|
|
1599
1774
|
if (hasAttribute(elt, 'hx-' + verb)) {
|
|
1600
1775
|
const path = getAttributeValue(elt, 'hx-' + verb)
|
|
1601
1776
|
explicitAction = true
|
|
1602
1777
|
nodeData.path = path
|
|
1603
1778
|
nodeData.verb = verb
|
|
1604
|
-
triggerSpecs.forEach(function
|
|
1605
|
-
addTriggerHandler(elt, triggerSpec, nodeData, function
|
|
1779
|
+
triggerSpecs.forEach(function(triggerSpec) {
|
|
1780
|
+
addTriggerHandler(elt, triggerSpec, nodeData, function(elt, evt) {
|
|
1606
1781
|
if (closest(elt, htmx.config.disableSelector)) {
|
|
1607
1782
|
cleanUpElement(elt)
|
|
1608
1783
|
return
|
|
@@ -1615,7 +1790,7 @@ const htmx = (function () {
|
|
|
1615
1790
|
return explicitAction
|
|
1616
1791
|
}
|
|
1617
1792
|
|
|
1618
|
-
function addTriggerHandler
|
|
1793
|
+
function addTriggerHandler(elt, triggerSpec, nodeData, handler) {
|
|
1619
1794
|
if (triggerSpec.trigger === 'revealed') {
|
|
1620
1795
|
initScrollHandler()
|
|
1621
1796
|
addEventListener(elt, handler, nodeData, triggerSpec)
|
|
@@ -1628,7 +1803,7 @@ const htmx = (function () {
|
|
|
1628
1803
|
if (triggerSpec.threshold) {
|
|
1629
1804
|
observerOptions.threshold = parseFloat(triggerSpec.threshold)
|
|
1630
1805
|
}
|
|
1631
|
-
const observer = new IntersectionObserver(function
|
|
1806
|
+
const observer = new IntersectionObserver(function(entries) {
|
|
1632
1807
|
for (let i = 0; i < entries.length; i++) {
|
|
1633
1808
|
const entry = entries[i]
|
|
1634
1809
|
if (entry.isIntersecting) {
|
|
@@ -1651,42 +1826,7 @@ const htmx = (function () {
|
|
|
1651
1826
|
}
|
|
1652
1827
|
}
|
|
1653
1828
|
|
|
1654
|
-
function
|
|
1655
|
-
if (htmx.config.allowScriptTags && (script.type === 'text/javascript' || script.type === 'module' || script.type === '')) {
|
|
1656
|
-
const newScript = getDocument().createElement('script')
|
|
1657
|
-
forEach(script.attributes, function (attr) {
|
|
1658
|
-
newScript.setAttribute(attr.name, attr.value)
|
|
1659
|
-
})
|
|
1660
|
-
newScript.textContent = script.textContent
|
|
1661
|
-
newScript.async = false
|
|
1662
|
-
if (htmx.config.inlineScriptNonce) {
|
|
1663
|
-
newScript.nonce = htmx.config.inlineScriptNonce
|
|
1664
|
-
}
|
|
1665
|
-
const parent = script.parentElement
|
|
1666
|
-
|
|
1667
|
-
try {
|
|
1668
|
-
parent.insertBefore(newScript, script)
|
|
1669
|
-
} catch (e) {
|
|
1670
|
-
logError(e)
|
|
1671
|
-
} finally {
|
|
1672
|
-
// remove old script element, but only if it is still in DOM
|
|
1673
|
-
if (script.parentElement) {
|
|
1674
|
-
script.parentElement.removeChild(script)
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1678
|
-
}
|
|
1679
|
-
|
|
1680
|
-
function processScripts (elt) {
|
|
1681
|
-
if (matches(elt, 'script')) {
|
|
1682
|
-
evalScript(elt)
|
|
1683
|
-
}
|
|
1684
|
-
forEach(findAll(elt, 'script'), function (script) {
|
|
1685
|
-
evalScript(script)
|
|
1686
|
-
})
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
|
-
function shouldProcessHxOn (elt) {
|
|
1829
|
+
function shouldProcessHxOn(elt) {
|
|
1690
1830
|
const attributes = elt.attributes
|
|
1691
1831
|
for (let j = 0; j < attributes.length; j++) {
|
|
1692
1832
|
const attrName = attributes[j].name
|
|
@@ -1698,7 +1838,7 @@ const htmx = (function () {
|
|
|
1698
1838
|
return false
|
|
1699
1839
|
}
|
|
1700
1840
|
|
|
1701
|
-
function findHxOnWildcardElements
|
|
1841
|
+
function findHxOnWildcardElements(elt) {
|
|
1702
1842
|
let node = null
|
|
1703
1843
|
const elements = []
|
|
1704
1844
|
|
|
@@ -1714,7 +1854,7 @@ const htmx = (function () {
|
|
|
1714
1854
|
return elements
|
|
1715
1855
|
}
|
|
1716
1856
|
|
|
1717
|
-
function findElementsToProcess
|
|
1857
|
+
function findElementsToProcess(elt) {
|
|
1718
1858
|
if (elt.querySelectorAll) {
|
|
1719
1859
|
const boostedSelector = ', [hx-boost] a, [data-hx-boost] a, a[hx-boost], a[data-hx-boost]'
|
|
1720
1860
|
const results = elt.querySelectorAll(VERB_SELECTOR + boostedSelector + ", form, [type='submit']," +
|
|
@@ -1727,20 +1867,20 @@ const htmx = (function () {
|
|
|
1727
1867
|
|
|
1728
1868
|
// Handle submit buttons/inputs that have the form attribute set
|
|
1729
1869
|
// see https://developer.mozilla.org/docs/Web/HTML/Element/button
|
|
1730
|
-
function maybeSetLastButtonClicked
|
|
1870
|
+
function maybeSetLastButtonClicked(evt) {
|
|
1731
1871
|
const elt = closest(evt.target, "button, input[type='submit']")
|
|
1732
1872
|
const internalData = getRelatedFormData(evt)
|
|
1733
1873
|
if (internalData) {
|
|
1734
1874
|
internalData.lastButtonClicked = elt
|
|
1735
1875
|
}
|
|
1736
1876
|
};
|
|
1737
|
-
function maybeUnsetLastButtonClicked
|
|
1877
|
+
function maybeUnsetLastButtonClicked(evt) {
|
|
1738
1878
|
const internalData = getRelatedFormData(evt)
|
|
1739
1879
|
if (internalData) {
|
|
1740
1880
|
internalData.lastButtonClicked = null
|
|
1741
1881
|
}
|
|
1742
1882
|
}
|
|
1743
|
-
function getRelatedFormData
|
|
1883
|
+
function getRelatedFormData(evt) {
|
|
1744
1884
|
const elt = closest(evt.target, "button, input[type='submit']")
|
|
1745
1885
|
if (!elt) {
|
|
1746
1886
|
return
|
|
@@ -1751,7 +1891,7 @@ const htmx = (function () {
|
|
|
1751
1891
|
}
|
|
1752
1892
|
return getInternalData(form)
|
|
1753
1893
|
}
|
|
1754
|
-
function initButtonTracking
|
|
1894
|
+
function initButtonTracking(elt) {
|
|
1755
1895
|
// need to handle both click and focus in:
|
|
1756
1896
|
// focusin - in case someone tabs in to a button and hits the space bar
|
|
1757
1897
|
// click - on OSX buttons do not focus on click see https://bugs.webkit.org/show_bug.cgi?id=13724
|
|
@@ -1760,7 +1900,7 @@ const htmx = (function () {
|
|
|
1760
1900
|
elt.addEventListener('focusout', maybeUnsetLastButtonClicked)
|
|
1761
1901
|
}
|
|
1762
1902
|
|
|
1763
|
-
function countCurlies
|
|
1903
|
+
function countCurlies(line) {
|
|
1764
1904
|
const tokens = tokenizeString(line)
|
|
1765
1905
|
let netCurlies = 0
|
|
1766
1906
|
for (let i = 0; i < tokens.length; i++) {
|
|
@@ -1774,14 +1914,14 @@ const htmx = (function () {
|
|
|
1774
1914
|
return netCurlies
|
|
1775
1915
|
}
|
|
1776
1916
|
|
|
1777
|
-
function addHxOnEventHandler
|
|
1917
|
+
function addHxOnEventHandler(elt, eventName, code) {
|
|
1778
1918
|
const nodeData = getInternalData(elt)
|
|
1779
1919
|
if (!Array.isArray(nodeData.onHandlers)) {
|
|
1780
1920
|
nodeData.onHandlers = []
|
|
1781
1921
|
}
|
|
1782
1922
|
let func
|
|
1783
|
-
const listener = function
|
|
1784
|
-
return maybeEval(elt, function
|
|
1923
|
+
const listener = function(e) {
|
|
1924
|
+
return maybeEval(elt, function() {
|
|
1785
1925
|
if (!func) {
|
|
1786
1926
|
func = new Function('event', code)
|
|
1787
1927
|
}
|
|
@@ -1792,7 +1932,7 @@ const htmx = (function () {
|
|
|
1792
1932
|
nodeData.onHandlers.push({ event: eventName, listener })
|
|
1793
1933
|
}
|
|
1794
1934
|
|
|
1795
|
-
function processHxOnWildcard
|
|
1935
|
+
function processHxOnWildcard(elt) {
|
|
1796
1936
|
// wipe any previous on handlers so that this function takes precedence
|
|
1797
1937
|
deInitOnHandlers(elt)
|
|
1798
1938
|
|
|
@@ -1819,7 +1959,7 @@ const htmx = (function () {
|
|
|
1819
1959
|
}
|
|
1820
1960
|
}
|
|
1821
1961
|
|
|
1822
|
-
function initNode
|
|
1962
|
+
function initNode(elt) {
|
|
1823
1963
|
if (closest(elt, htmx.config.disableSelector)) {
|
|
1824
1964
|
cleanUpElement(elt)
|
|
1825
1965
|
return
|
|
@@ -1844,9 +1984,9 @@ const htmx = (function () {
|
|
|
1844
1984
|
if (getClosestAttributeValue(elt, 'hx-boost') === 'true') {
|
|
1845
1985
|
boostElement(elt, nodeData, triggerSpecs)
|
|
1846
1986
|
} else if (hasAttribute(elt, 'hx-trigger')) {
|
|
1847
|
-
triggerSpecs.forEach(function
|
|
1987
|
+
triggerSpecs.forEach(function(triggerSpec) {
|
|
1848
1988
|
// For "naked" triggers, don't do anything at all
|
|
1849
|
-
addTriggerHandler(elt, triggerSpec, nodeData, function
|
|
1989
|
+
addTriggerHandler(elt, triggerSpec, nodeData, function() {
|
|
1850
1990
|
})
|
|
1851
1991
|
})
|
|
1852
1992
|
}
|
|
@@ -1862,14 +2002,14 @@ const htmx = (function () {
|
|
|
1862
2002
|
}
|
|
1863
2003
|
}
|
|
1864
2004
|
|
|
1865
|
-
function processNode
|
|
2005
|
+
function processNode(elt) {
|
|
1866
2006
|
elt = resolveTarget(elt)
|
|
1867
2007
|
if (closest(elt, htmx.config.disableSelector)) {
|
|
1868
2008
|
cleanUpElement(elt)
|
|
1869
2009
|
return
|
|
1870
2010
|
}
|
|
1871
2011
|
initNode(elt)
|
|
1872
|
-
forEach(findElementsToProcess(elt), function
|
|
2012
|
+
forEach(findElementsToProcess(elt), function(child) { initNode(child) })
|
|
1873
2013
|
forEach(findHxOnWildcardElements(elt), processHxOnWildcard)
|
|
1874
2014
|
}
|
|
1875
2015
|
|
|
@@ -1877,11 +2017,11 @@ const htmx = (function () {
|
|
|
1877
2017
|
// Event/Log Support
|
|
1878
2018
|
//= ===================================================================
|
|
1879
2019
|
|
|
1880
|
-
function kebabEventName
|
|
2020
|
+
function kebabEventName(str) {
|
|
1881
2021
|
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
|
|
1882
2022
|
}
|
|
1883
2023
|
|
|
1884
|
-
function makeEvent
|
|
2024
|
+
function makeEvent(eventName, detail) {
|
|
1885
2025
|
let evt
|
|
1886
2026
|
if (window.CustomEvent && typeof window.CustomEvent === 'function') {
|
|
1887
2027
|
// TODO: `composed: true` here is a hack to make global event handlers work with events in shadow DOM
|
|
@@ -1894,11 +2034,11 @@ const htmx = (function () {
|
|
|
1894
2034
|
return evt
|
|
1895
2035
|
}
|
|
1896
2036
|
|
|
1897
|
-
function triggerErrorEvent
|
|
2037
|
+
function triggerErrorEvent(elt, eventName, detail) {
|
|
1898
2038
|
triggerEvent(elt, eventName, mergeObjects({ error: eventName }, detail))
|
|
1899
2039
|
}
|
|
1900
2040
|
|
|
1901
|
-
function ignoreEventForLogging
|
|
2041
|
+
function ignoreEventForLogging(eventName) {
|
|
1902
2042
|
return eventName === 'htmx:afterProcessNode'
|
|
1903
2043
|
}
|
|
1904
2044
|
|
|
@@ -1911,8 +2051,8 @@ const htmx = (function () {
|
|
|
1911
2051
|
* @param {(extension:import("./htmx").HtmxExtension) => void} toDo
|
|
1912
2052
|
* @returns void
|
|
1913
2053
|
*/
|
|
1914
|
-
function withExtensions
|
|
1915
|
-
forEach(getExtensions(elt), function
|
|
2054
|
+
function withExtensions(elt, toDo) {
|
|
2055
|
+
forEach(getExtensions(elt), function(extension) {
|
|
1916
2056
|
try {
|
|
1917
2057
|
toDo(extension)
|
|
1918
2058
|
} catch (e) {
|
|
@@ -1921,7 +2061,7 @@ const htmx = (function () {
|
|
|
1921
2061
|
})
|
|
1922
2062
|
}
|
|
1923
2063
|
|
|
1924
|
-
function logError
|
|
2064
|
+
function logError(msg) {
|
|
1925
2065
|
if (console.error) {
|
|
1926
2066
|
console.error(msg)
|
|
1927
2067
|
} else if (console.log) {
|
|
@@ -1929,7 +2069,7 @@ const htmx = (function () {
|
|
|
1929
2069
|
}
|
|
1930
2070
|
}
|
|
1931
2071
|
|
|
1932
|
-
function triggerEvent
|
|
2072
|
+
function triggerEvent(elt, eventName, detail) {
|
|
1933
2073
|
elt = resolveTarget(elt)
|
|
1934
2074
|
if (detail == null) {
|
|
1935
2075
|
detail = {}
|
|
@@ -1949,7 +2089,7 @@ const htmx = (function () {
|
|
|
1949
2089
|
const kebabedEvent = makeEvent(kebabName, event.detail)
|
|
1950
2090
|
eventResult = eventResult && elt.dispatchEvent(kebabedEvent)
|
|
1951
2091
|
}
|
|
1952
|
-
withExtensions(elt, function
|
|
2092
|
+
withExtensions(elt, function(extension) {
|
|
1953
2093
|
eventResult = eventResult && (extension.onEvent(eventName, event) !== false && !event.defaultPrevented)
|
|
1954
2094
|
})
|
|
1955
2095
|
return eventResult
|
|
@@ -1960,16 +2100,21 @@ const htmx = (function () {
|
|
|
1960
2100
|
//= ===================================================================
|
|
1961
2101
|
let currentPathForHistory = location.pathname + location.search
|
|
1962
2102
|
|
|
1963
|
-
function getHistoryElement
|
|
2103
|
+
function getHistoryElement() {
|
|
1964
2104
|
const historyElt = getDocument().querySelector('[hx-history-elt],[data-hx-history-elt]')
|
|
1965
2105
|
return historyElt || getDocument().body
|
|
1966
2106
|
}
|
|
1967
2107
|
|
|
1968
|
-
function saveToHistoryCache
|
|
2108
|
+
function saveToHistoryCache(url, rootElt) {
|
|
1969
2109
|
if (!canAccessLocalStorage()) {
|
|
1970
2110
|
return
|
|
1971
2111
|
}
|
|
1972
2112
|
|
|
2113
|
+
// get state to save
|
|
2114
|
+
const innerHTML = cleanInnerHtmlForHistory(rootElt)
|
|
2115
|
+
const title = getDocument().title
|
|
2116
|
+
const scroll = window.scrollY
|
|
2117
|
+
|
|
1973
2118
|
if (htmx.config.historyCacheSize <= 0) {
|
|
1974
2119
|
// make sure that an eventually already existing cache is purged
|
|
1975
2120
|
localStorage.removeItem('htmx-history-cache')
|
|
@@ -1985,12 +2130,17 @@ const htmx = (function () {
|
|
|
1985
2130
|
break
|
|
1986
2131
|
}
|
|
1987
2132
|
}
|
|
1988
|
-
|
|
2133
|
+
|
|
2134
|
+
const newHistoryItem = { url, content: innerHTML, title, scroll }
|
|
2135
|
+
|
|
1989
2136
|
triggerEvent(getDocument().body, 'htmx:historyItemCreated', { item: newHistoryItem, cache: historyCache })
|
|
2137
|
+
|
|
1990
2138
|
historyCache.push(newHistoryItem)
|
|
1991
2139
|
while (historyCache.length > htmx.config.historyCacheSize) {
|
|
1992
2140
|
historyCache.shift()
|
|
1993
2141
|
}
|
|
2142
|
+
|
|
2143
|
+
// keep trying to save the cache until it succeeds or is empty
|
|
1994
2144
|
while (historyCache.length > 0) {
|
|
1995
2145
|
try {
|
|
1996
2146
|
localStorage.setItem('htmx-history-cache', JSON.stringify(historyCache))
|
|
@@ -2002,7 +2152,7 @@ const htmx = (function () {
|
|
|
2002
2152
|
}
|
|
2003
2153
|
}
|
|
2004
2154
|
|
|
2005
|
-
function getCachedHistory
|
|
2155
|
+
function getCachedHistory(url) {
|
|
2006
2156
|
if (!canAccessLocalStorage()) {
|
|
2007
2157
|
return null
|
|
2008
2158
|
}
|
|
@@ -2018,16 +2168,16 @@ const htmx = (function () {
|
|
|
2018
2168
|
return null
|
|
2019
2169
|
}
|
|
2020
2170
|
|
|
2021
|
-
function cleanInnerHtmlForHistory
|
|
2171
|
+
function cleanInnerHtmlForHistory(elt) {
|
|
2022
2172
|
const className = htmx.config.requestClass
|
|
2023
2173
|
const clone = elt.cloneNode(true)
|
|
2024
|
-
forEach(findAll(clone, '.' + className), function
|
|
2174
|
+
forEach(findAll(clone, '.' + className), function(child) {
|
|
2025
2175
|
removeClassFromElement(child, className)
|
|
2026
2176
|
})
|
|
2027
2177
|
return clone.innerHTML
|
|
2028
2178
|
}
|
|
2029
2179
|
|
|
2030
|
-
function saveCurrentPageToHistory
|
|
2180
|
+
function saveCurrentPageToHistory() {
|
|
2031
2181
|
const elt = getHistoryElement()
|
|
2032
2182
|
const path = currentPathForHistory || location.pathname + location.search
|
|
2033
2183
|
|
|
@@ -2045,13 +2195,13 @@ const htmx = (function () {
|
|
|
2045
2195
|
}
|
|
2046
2196
|
if (!disableHistoryCache) {
|
|
2047
2197
|
triggerEvent(getDocument().body, 'htmx:beforeHistorySave', { path, historyElt: elt })
|
|
2048
|
-
saveToHistoryCache(path,
|
|
2198
|
+
saveToHistoryCache(path, elt)
|
|
2049
2199
|
}
|
|
2050
2200
|
|
|
2051
2201
|
if (htmx.config.historyEnabled) history.replaceState({ htmx: true }, getDocument().title, window.location.href)
|
|
2052
2202
|
}
|
|
2053
2203
|
|
|
2054
|
-
function pushUrlIntoHistory
|
|
2204
|
+
function pushUrlIntoHistory(path) {
|
|
2055
2205
|
// remove the cache buster parameter, if any
|
|
2056
2206
|
if (htmx.config.getCacheBusterParam) {
|
|
2057
2207
|
path = path.replace(/org\.htmx\.cache-buster=[^&]*&?/, '')
|
|
@@ -2065,18 +2215,18 @@ const htmx = (function () {
|
|
|
2065
2215
|
currentPathForHistory = path
|
|
2066
2216
|
}
|
|
2067
2217
|
|
|
2068
|
-
function replaceUrlInHistory
|
|
2218
|
+
function replaceUrlInHistory(path) {
|
|
2069
2219
|
if (htmx.config.historyEnabled) history.replaceState({ htmx: true }, '', path)
|
|
2070
2220
|
currentPathForHistory = path
|
|
2071
2221
|
}
|
|
2072
2222
|
|
|
2073
|
-
function settleImmediately
|
|
2074
|
-
forEach(tasks, function
|
|
2223
|
+
function settleImmediately(tasks) {
|
|
2224
|
+
forEach(tasks, function(task) {
|
|
2075
2225
|
task.call()
|
|
2076
2226
|
})
|
|
2077
2227
|
}
|
|
2078
2228
|
|
|
2079
|
-
function loadHistoryFromServer
|
|
2229
|
+
function loadHistoryFromServer(path) {
|
|
2080
2230
|
const request = new XMLHttpRequest()
|
|
2081
2231
|
const details = { path, xhr: request }
|
|
2082
2232
|
triggerEvent(getDocument().body, 'htmx:historyCacheMiss', details)
|
|
@@ -2084,25 +2234,18 @@ const htmx = (function () {
|
|
|
2084
2234
|
request.setRequestHeader('HX-Request', 'true')
|
|
2085
2235
|
request.setRequestHeader('HX-History-Restore-Request', 'true')
|
|
2086
2236
|
request.setRequestHeader('HX-Current-URL', getDocument().location.href)
|
|
2087
|
-
request.onload = function
|
|
2237
|
+
request.onload = function() {
|
|
2088
2238
|
if (this.status >= 200 && this.status < 400) {
|
|
2089
2239
|
triggerEvent(getDocument().body, 'htmx:historyCacheMissLoad', details)
|
|
2090
|
-
|
|
2240
|
+
const fragment = makeFragment(this.response)
|
|
2091
2241
|
// @ts-ignore
|
|
2092
|
-
|
|
2242
|
+
const content = fragment.querySelector('[hx-history-elt],[data-hx-history-elt]') || fragment
|
|
2093
2243
|
const historyElement = getHistoryElement()
|
|
2094
2244
|
const settleInfo = makeSettleInfo(historyElement)
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
const titleElt = find('title')
|
|
2098
|
-
if (titleElt) {
|
|
2099
|
-
titleElt.innerHTML = title
|
|
2100
|
-
} else {
|
|
2101
|
-
window.document.title = title
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2245
|
+
handleTitle(fragment.title)
|
|
2246
|
+
|
|
2104
2247
|
// @ts-ignore
|
|
2105
|
-
swapInnerHTML(historyElement,
|
|
2248
|
+
swapInnerHTML(historyElement, content, settleInfo)
|
|
2106
2249
|
settleImmediately(settleInfo.tasks)
|
|
2107
2250
|
currentPathForHistory = path
|
|
2108
2251
|
triggerEvent(getDocument().body, 'htmx:historyRestore', { path, cacheMiss: true, serverResponse: this.response })
|
|
@@ -2113,7 +2256,7 @@ const htmx = (function () {
|
|
|
2113
2256
|
request.send()
|
|
2114
2257
|
}
|
|
2115
2258
|
|
|
2116
|
-
function restoreHistory
|
|
2259
|
+
function restoreHistory(path) {
|
|
2117
2260
|
saveCurrentPageToHistory()
|
|
2118
2261
|
path = path || location.pathname + location.search
|
|
2119
2262
|
const cached = getCachedHistory(path)
|
|
@@ -2121,10 +2264,10 @@ const htmx = (function () {
|
|
|
2121
2264
|
const fragment = makeFragment(cached.content)
|
|
2122
2265
|
const historyElement = getHistoryElement()
|
|
2123
2266
|
const settleInfo = makeSettleInfo(historyElement)
|
|
2267
|
+
handleTitle(fragment.title)
|
|
2124
2268
|
swapInnerHTML(historyElement, fragment, settleInfo)
|
|
2125
2269
|
settleImmediately(settleInfo.tasks)
|
|
2126
|
-
|
|
2127
|
-
setTimeout(function () {
|
|
2270
|
+
setTimeout(function() {
|
|
2128
2271
|
window.scrollTo(0, cached.scroll)
|
|
2129
2272
|
}, 0) // next 'tick', so browser has time to render layout
|
|
2130
2273
|
currentPathForHistory = path
|
|
@@ -2139,12 +2282,12 @@ const htmx = (function () {
|
|
|
2139
2282
|
}
|
|
2140
2283
|
}
|
|
2141
2284
|
|
|
2142
|
-
function addRequestIndicatorClasses
|
|
2285
|
+
function addRequestIndicatorClasses(elt) {
|
|
2143
2286
|
let indicators = findAttributeTargets(elt, 'hx-indicator')
|
|
2144
2287
|
if (indicators == null) {
|
|
2145
2288
|
indicators = [elt]
|
|
2146
2289
|
}
|
|
2147
|
-
forEach(indicators, function
|
|
2290
|
+
forEach(indicators, function(ic) {
|
|
2148
2291
|
const internalData = getInternalData(ic)
|
|
2149
2292
|
internalData.requestCount = (internalData.requestCount || 0) + 1
|
|
2150
2293
|
ic.classList.add.call(ic.classList, htmx.config.requestClass)
|
|
@@ -2152,12 +2295,12 @@ const htmx = (function () {
|
|
|
2152
2295
|
return indicators
|
|
2153
2296
|
}
|
|
2154
2297
|
|
|
2155
|
-
function disableElements
|
|
2298
|
+
function disableElements(elt) {
|
|
2156
2299
|
let disabledElts = findAttributeTargets(elt, 'hx-disabled-elt')
|
|
2157
2300
|
if (disabledElts == null) {
|
|
2158
2301
|
disabledElts = []
|
|
2159
2302
|
}
|
|
2160
|
-
forEach(disabledElts, function
|
|
2303
|
+
forEach(disabledElts, function(disabledElement) {
|
|
2161
2304
|
const internalData = getInternalData(disabledElement)
|
|
2162
2305
|
internalData.requestCount = (internalData.requestCount || 0) + 1
|
|
2163
2306
|
disabledElement.setAttribute('disabled', '')
|
|
@@ -2165,15 +2308,15 @@ const htmx = (function () {
|
|
|
2165
2308
|
return disabledElts
|
|
2166
2309
|
}
|
|
2167
2310
|
|
|
2168
|
-
function removeRequestIndicators
|
|
2169
|
-
forEach(indicators, function
|
|
2311
|
+
function removeRequestIndicators(indicators, disabled) {
|
|
2312
|
+
forEach(indicators, function(ic) {
|
|
2170
2313
|
const internalData = getInternalData(ic)
|
|
2171
2314
|
internalData.requestCount = (internalData.requestCount || 0) - 1
|
|
2172
2315
|
if (internalData.requestCount === 0) {
|
|
2173
2316
|
ic.classList.remove.call(ic.classList, htmx.config.requestClass)
|
|
2174
2317
|
}
|
|
2175
2318
|
})
|
|
2176
|
-
forEach(disabled, function
|
|
2319
|
+
forEach(disabled, function(disabledElement) {
|
|
2177
2320
|
const internalData = getInternalData(disabledElement)
|
|
2178
2321
|
internalData.requestCount = (internalData.requestCount || 0) - 1
|
|
2179
2322
|
if (internalData.requestCount === 0) {
|
|
@@ -2186,7 +2329,12 @@ const htmx = (function () {
|
|
|
2186
2329
|
// Input Value Processing
|
|
2187
2330
|
//= ===================================================================
|
|
2188
2331
|
|
|
2189
|
-
|
|
2332
|
+
/**
|
|
2333
|
+
* @param {HTMLElement[]} processed
|
|
2334
|
+
* @param {HTMLElement} elt
|
|
2335
|
+
* @returns {boolean}
|
|
2336
|
+
*/
|
|
2337
|
+
function haveSeenNode(processed, elt) {
|
|
2190
2338
|
for (let i = 0; i < processed.length; i++) {
|
|
2191
2339
|
const node = processed[i]
|
|
2192
2340
|
if (node.isSameNode(elt)) {
|
|
@@ -2196,8 +2344,8 @@ const htmx = (function () {
|
|
|
2196
2344
|
return false
|
|
2197
2345
|
}
|
|
2198
2346
|
|
|
2199
|
-
function shouldInclude
|
|
2200
|
-
if (elt.name === '' || elt.name == null || elt.disabled) {
|
|
2347
|
+
function shouldInclude(elt) {
|
|
2348
|
+
if (elt.name === '' || elt.name == null || elt.disabled || closest(elt, 'fieldset[disabled]')) {
|
|
2201
2349
|
return false
|
|
2202
2350
|
}
|
|
2203
2351
|
// ignore "submitter" types (see jQuery src/serialize.js)
|
|
@@ -2210,30 +2358,43 @@ const htmx = (function () {
|
|
|
2210
2358
|
return true
|
|
2211
2359
|
}
|
|
2212
2360
|
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2361
|
+
/** @param {string} name
|
|
2362
|
+
* @param {string|Array} value
|
|
2363
|
+
* @param {FormData} formData */
|
|
2364
|
+
function addValueToFormData(name, value, formData) {
|
|
2216
2365
|
if (name != null && value != null) {
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
values[name] = value
|
|
2220
|
-
} else if (Array.isArray(current)) {
|
|
2221
|
-
if (Array.isArray(value)) {
|
|
2222
|
-
values[name] = current.concat(value)
|
|
2223
|
-
} else {
|
|
2224
|
-
current.push(value)
|
|
2225
|
-
}
|
|
2366
|
+
if (Array.isArray(value)) {
|
|
2367
|
+
value.forEach(function(v) { formData.append(name, v) })
|
|
2226
2368
|
} else {
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2369
|
+
formData.append(name, value)
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
/** @param {string} name
|
|
2375
|
+
* @param {string|Array} value
|
|
2376
|
+
* @param {FormData} formData */
|
|
2377
|
+
function removeValueFromFormData(name, value, formData) {
|
|
2378
|
+
if (name != null && value != null) {
|
|
2379
|
+
let values = formData.getAll(name)
|
|
2380
|
+
if (Array.isArray(value)) {
|
|
2381
|
+
values = values.filter(v => value.indexOf(v) < 0)
|
|
2382
|
+
} else {
|
|
2383
|
+
values = values.filter(v => v !== value)
|
|
2232
2384
|
}
|
|
2385
|
+
formData.delete(name)
|
|
2386
|
+
forEach(values, v => formData.append(name, v))
|
|
2233
2387
|
}
|
|
2234
2388
|
}
|
|
2235
2389
|
|
|
2236
|
-
|
|
2390
|
+
/**
|
|
2391
|
+
* @param {HTMLElement[]} processed
|
|
2392
|
+
* @param {FormData} formData
|
|
2393
|
+
* @param {HtmxElementValidationError[]} errors
|
|
2394
|
+
* @param {HTMLElement|HTMLInputElement|HTMLFormElement} elt
|
|
2395
|
+
* @param {boolean} validate
|
|
2396
|
+
*/
|
|
2397
|
+
function processInputValue(processed, formData, errors, elt, validate) {
|
|
2237
2398
|
if (elt == null || haveSeenNode(processed, elt)) {
|
|
2238
2399
|
return
|
|
2239
2400
|
} else {
|
|
@@ -2243,26 +2404,47 @@ const htmx = (function () {
|
|
|
2243
2404
|
const name = getRawAttribute(elt, 'name')
|
|
2244
2405
|
let value = elt.value
|
|
2245
2406
|
if (elt.multiple && elt.tagName === 'SELECT') {
|
|
2246
|
-
value = toArray(elt.querySelectorAll('option:checked')).map(function
|
|
2407
|
+
value = toArray(elt.querySelectorAll('option:checked')).map(function(e) { return e.value })
|
|
2247
2408
|
}
|
|
2248
2409
|
// include file inputs
|
|
2249
2410
|
if (elt.files) {
|
|
2250
2411
|
value = toArray(elt.files)
|
|
2251
2412
|
}
|
|
2252
|
-
|
|
2413
|
+
addValueToFormData(name, value, formData)
|
|
2253
2414
|
if (validate) {
|
|
2254
2415
|
validateElement(elt, errors)
|
|
2255
2416
|
}
|
|
2256
2417
|
}
|
|
2257
2418
|
if (matches(elt, 'form')) {
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2419
|
+
forEach(elt.elements, function(input) {
|
|
2420
|
+
if (processed.indexOf(input) >= 0) {
|
|
2421
|
+
// The input has already been processed and added to the values, but the FormData that will be
|
|
2422
|
+
// constructed right after on the form, will include it once again. So remove that input's value
|
|
2423
|
+
// now to avoid duplicates
|
|
2424
|
+
removeValueFromFormData(input.name, input.value, formData)
|
|
2425
|
+
} else {
|
|
2426
|
+
processed.push(input)
|
|
2427
|
+
}
|
|
2428
|
+
if (validate) {
|
|
2429
|
+
validateElement(input, errors)
|
|
2430
|
+
}
|
|
2431
|
+
})
|
|
2432
|
+
new FormData(elt).forEach(function(value, name) {
|
|
2433
|
+
addValueToFormData(name, value, formData)
|
|
2261
2434
|
})
|
|
2262
2435
|
}
|
|
2263
2436
|
}
|
|
2264
2437
|
|
|
2265
|
-
|
|
2438
|
+
/**
|
|
2439
|
+
* @typedef {{elt: HTMLElement, message: string, validity: ValidityState}} HtmxElementValidationError
|
|
2440
|
+
*/
|
|
2441
|
+
|
|
2442
|
+
/**
|
|
2443
|
+
*
|
|
2444
|
+
* @param {HTMLElement|HTMLObjectElement} element
|
|
2445
|
+
* @param {HtmxElementValidationError[]} errors
|
|
2446
|
+
*/
|
|
2447
|
+
function validateElement(element, errors) {
|
|
2266
2448
|
if (element.willValidate) {
|
|
2267
2449
|
triggerEvent(element, 'htmx:validation:validate')
|
|
2268
2450
|
if (!element.checkValidity()) {
|
|
@@ -2273,13 +2455,32 @@ const htmx = (function () {
|
|
|
2273
2455
|
}
|
|
2274
2456
|
|
|
2275
2457
|
/**
|
|
2276
|
-
|
|
2458
|
+
* Override values in the one FormData with those from another.
|
|
2459
|
+
* @param {FormData} receiver the formdata that will be mutated
|
|
2460
|
+
* @param {FormData} donor the formdata that will provide the overriding values
|
|
2461
|
+
* @returns {FormData} the {@linkcode receiver}
|
|
2462
|
+
*/
|
|
2463
|
+
function overrideFormData(receiver, donor) {
|
|
2464
|
+
for (const key of donor.keys()) {
|
|
2465
|
+
receiver.delete(key)
|
|
2466
|
+
donor.getAll(key).forEach(function(value) {
|
|
2467
|
+
receiver.append(key, value)
|
|
2468
|
+
})
|
|
2469
|
+
}
|
|
2470
|
+
return receiver
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
/**
|
|
2474
|
+
* @param {HTMLElement|HTMLFormElement} elt
|
|
2277
2475
|
* @param {string} verb
|
|
2476
|
+
* @returns {{errors: HtmxElementValidationError[], formData: FormData, values: Object}}
|
|
2278
2477
|
*/
|
|
2279
|
-
function getInputValues
|
|
2478
|
+
function getInputValues(elt, verb) {
|
|
2479
|
+
/** @type HTMLElement[] */
|
|
2280
2480
|
const processed = []
|
|
2281
|
-
|
|
2282
|
-
const
|
|
2481
|
+
const formData = new FormData()
|
|
2482
|
+
const priorityFormData = new FormData()
|
|
2483
|
+
/** @type HtmxElementValidationError[] */
|
|
2283
2484
|
const errors = []
|
|
2284
2485
|
const internalData = getInternalData(elt)
|
|
2285
2486
|
if (internalData.lastButtonClicked && !bodyContains(internalData.lastButtonClicked)) {
|
|
@@ -2295,39 +2496,45 @@ const htmx = (function () {
|
|
|
2295
2496
|
|
|
2296
2497
|
// for a non-GET include the closest form
|
|
2297
2498
|
if (verb !== 'get') {
|
|
2298
|
-
processInputValue(processed,
|
|
2499
|
+
processInputValue(processed, priorityFormData, errors, closest(elt, 'form'), validate)
|
|
2299
2500
|
}
|
|
2300
2501
|
|
|
2301
2502
|
// include the element itself
|
|
2302
|
-
processInputValue(processed,
|
|
2503
|
+
processInputValue(processed, formData, errors, elt, validate)
|
|
2303
2504
|
|
|
2304
2505
|
// if a button or submit was clicked last, include its value
|
|
2305
2506
|
if (internalData.lastButtonClicked || elt.tagName === 'BUTTON' ||
|
|
2306
2507
|
(elt.tagName === 'INPUT' && getRawAttribute(elt, 'type') === 'submit')) {
|
|
2307
2508
|
const button = internalData.lastButtonClicked || elt
|
|
2308
2509
|
const name = getRawAttribute(button, 'name')
|
|
2309
|
-
|
|
2510
|
+
addValueToFormData(name, button.value, priorityFormData)
|
|
2310
2511
|
}
|
|
2311
2512
|
|
|
2312
2513
|
// include any explicit includes
|
|
2313
2514
|
const includes = findAttributeTargets(elt, 'hx-include')
|
|
2314
|
-
forEach(includes, function
|
|
2315
|
-
processInputValue(processed,
|
|
2515
|
+
forEach(includes, function(node) {
|
|
2516
|
+
processInputValue(processed, formData, errors, node, validate)
|
|
2316
2517
|
// if a non-form is included, include any input values within it
|
|
2317
2518
|
if (!matches(node, 'form')) {
|
|
2318
|
-
forEach(node.querySelectorAll(INPUT_SELECTOR), function
|
|
2319
|
-
processInputValue(processed,
|
|
2519
|
+
forEach(node.querySelectorAll(INPUT_SELECTOR), function(descendant) {
|
|
2520
|
+
processInputValue(processed, formData, errors, descendant, validate)
|
|
2320
2521
|
})
|
|
2321
2522
|
}
|
|
2322
2523
|
})
|
|
2323
2524
|
|
|
2324
|
-
// form
|
|
2325
|
-
|
|
2525
|
+
// values from a <form> take precedence, overriding the regular values
|
|
2526
|
+
overrideFormData(formData, priorityFormData)
|
|
2326
2527
|
|
|
2327
|
-
return { errors, values }
|
|
2528
|
+
return { errors, formData, values: formDataProxy(formData) }
|
|
2328
2529
|
}
|
|
2329
2530
|
|
|
2330
|
-
|
|
2531
|
+
/**
|
|
2532
|
+
* @param {string} returnStr
|
|
2533
|
+
* @param {string} name
|
|
2534
|
+
* @param {any} realValue
|
|
2535
|
+
* @returns {string}
|
|
2536
|
+
*/
|
|
2537
|
+
function appendParam(returnStr, name, realValue) {
|
|
2331
2538
|
if (returnStr !== '') {
|
|
2332
2539
|
returnStr += '&'
|
|
2333
2540
|
}
|
|
@@ -2339,40 +2546,19 @@ const htmx = (function () {
|
|
|
2339
2546
|
return returnStr
|
|
2340
2547
|
}
|
|
2341
2548
|
|
|
2342
|
-
|
|
2549
|
+
/**
|
|
2550
|
+
* @param {FormData|Object} values
|
|
2551
|
+
* @returns string
|
|
2552
|
+
*/
|
|
2553
|
+
function urlEncode(values) {
|
|
2554
|
+
values = formDataFromObject(values)
|
|
2343
2555
|
let returnStr = ''
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
if (Array.isArray(value)) {
|
|
2348
|
-
forEach(value, function (v) {
|
|
2349
|
-
returnStr = appendParam(returnStr, name, v)
|
|
2350
|
-
})
|
|
2351
|
-
} else {
|
|
2352
|
-
returnStr = appendParam(returnStr, name, value)
|
|
2353
|
-
}
|
|
2354
|
-
}
|
|
2355
|
-
}
|
|
2556
|
+
values.forEach(function(value, key) {
|
|
2557
|
+
returnStr = appendParam(returnStr, key, value)
|
|
2558
|
+
})
|
|
2356
2559
|
return returnStr
|
|
2357
2560
|
}
|
|
2358
2561
|
|
|
2359
|
-
function makeFormData (values) {
|
|
2360
|
-
const formData = new FormData()
|
|
2361
|
-
for (var name in values) {
|
|
2362
|
-
if (values.hasOwnProperty(name)) {
|
|
2363
|
-
const value = values[name]
|
|
2364
|
-
if (Array.isArray(value)) {
|
|
2365
|
-
forEach(value, function (v) {
|
|
2366
|
-
formData.append(name, v)
|
|
2367
|
-
})
|
|
2368
|
-
} else {
|
|
2369
|
-
formData.append(name, value)
|
|
2370
|
-
}
|
|
2371
|
-
}
|
|
2372
|
-
}
|
|
2373
|
-
return formData
|
|
2374
|
-
}
|
|
2375
|
-
|
|
2376
2562
|
//= ===================================================================
|
|
2377
2563
|
// Ajax
|
|
2378
2564
|
//= ===================================================================
|
|
@@ -2383,7 +2569,7 @@ const htmx = (function () {
|
|
|
2383
2569
|
* @param {string} prompt
|
|
2384
2570
|
* @returns {Object} // TODO: Define/Improve HtmxHeaderSpecification
|
|
2385
2571
|
*/
|
|
2386
|
-
function getHeaders
|
|
2572
|
+
function getHeaders(elt, target, prompt) {
|
|
2387
2573
|
const headers = {
|
|
2388
2574
|
'HX-Request': 'true',
|
|
2389
2575
|
'HX-Trigger': getRawAttribute(elt, 'id'),
|
|
@@ -2405,28 +2591,30 @@ const htmx = (function () {
|
|
|
2405
2591
|
* filterValues takes an object containing form input values
|
|
2406
2592
|
* and returns a new object that only contains keys that are
|
|
2407
2593
|
* specified by the closest "hx-params" attribute
|
|
2408
|
-
* @param {
|
|
2594
|
+
* @param {FormData} inputValues
|
|
2409
2595
|
* @param {HTMLElement} elt
|
|
2410
|
-
* @returns {
|
|
2596
|
+
* @returns {FormData}
|
|
2411
2597
|
*/
|
|
2412
|
-
function filterValues
|
|
2598
|
+
function filterValues(inputValues, elt) {
|
|
2413
2599
|
const paramsValue = getClosestAttributeValue(elt, 'hx-params')
|
|
2414
2600
|
if (paramsValue) {
|
|
2415
2601
|
if (paramsValue === 'none') {
|
|
2416
|
-
return
|
|
2602
|
+
return new FormData()
|
|
2417
2603
|
} else if (paramsValue === '*') {
|
|
2418
2604
|
return inputValues
|
|
2419
2605
|
} else if (paramsValue.indexOf('not ') === 0) {
|
|
2420
|
-
forEach(paramsValue.substr(4).split(','), function
|
|
2606
|
+
forEach(paramsValue.substr(4).split(','), function(name) {
|
|
2421
2607
|
name = name.trim()
|
|
2422
|
-
delete
|
|
2608
|
+
inputValues.delete(name)
|
|
2423
2609
|
})
|
|
2424
2610
|
return inputValues
|
|
2425
2611
|
} else {
|
|
2426
|
-
const newValues =
|
|
2427
|
-
forEach(paramsValue.split(','), function
|
|
2612
|
+
const newValues = new FormData()
|
|
2613
|
+
forEach(paramsValue.split(','), function(name) {
|
|
2428
2614
|
name = name.trim()
|
|
2429
|
-
|
|
2615
|
+
if (inputValues.has(name)) {
|
|
2616
|
+
inputValues.getAll(name).forEach(function(value) { newValues.append(name, value) })
|
|
2617
|
+
}
|
|
2430
2618
|
})
|
|
2431
2619
|
return newValues
|
|
2432
2620
|
}
|
|
@@ -2435,18 +2623,19 @@ const htmx = (function () {
|
|
|
2435
2623
|
}
|
|
2436
2624
|
}
|
|
2437
2625
|
|
|
2438
|
-
function isAnchorLink
|
|
2626
|
+
function isAnchorLink(elt) {
|
|
2439
2627
|
return getRawAttribute(elt, 'href') && getRawAttribute(elt, 'href').indexOf('#') >= 0
|
|
2440
2628
|
}
|
|
2441
2629
|
|
|
2442
2630
|
/**
|
|
2443
2631
|
*
|
|
2444
2632
|
* @param {HTMLElement} elt
|
|
2445
|
-
* @param {
|
|
2633
|
+
* @param {import("./htmx").HtmxSwapStyle} swapInfoOverride
|
|
2446
2634
|
* @returns {import("./htmx").HtmxSwapSpecification}
|
|
2447
2635
|
*/
|
|
2448
|
-
function getSwapSpecification
|
|
2636
|
+
function getSwapSpecification(elt, swapInfoOverride) {
|
|
2449
2637
|
const swapInfo = swapInfoOverride || getClosestAttributeValue(elt, 'hx-swap')
|
|
2638
|
+
/** @type import("./htmx").HtmxSwapSpecification */
|
|
2450
2639
|
const swapSpec = {
|
|
2451
2640
|
swapStyle: getInternalData(elt).boosted ? 'innerHTML' : htmx.config.defaultSwapStyle,
|
|
2452
2641
|
swapDelay: htmx.config.defaultSwapDelay,
|
|
@@ -2496,14 +2685,20 @@ const htmx = (function () {
|
|
|
2496
2685
|
return swapSpec
|
|
2497
2686
|
}
|
|
2498
2687
|
|
|
2499
|
-
function usesFormData
|
|
2688
|
+
function usesFormData(elt) {
|
|
2500
2689
|
return getClosestAttributeValue(elt, 'hx-encoding') === 'multipart/form-data' ||
|
|
2501
2690
|
(matches(elt, 'form') && getRawAttribute(elt, 'enctype') === 'multipart/form-data')
|
|
2502
2691
|
}
|
|
2503
2692
|
|
|
2504
|
-
|
|
2693
|
+
/**
|
|
2694
|
+
* @param {XMLHttpRequest} xhr
|
|
2695
|
+
* @param {HTMLElement} elt
|
|
2696
|
+
* @param {FormData} filteredParameters
|
|
2697
|
+
* @returns {*|string|null}
|
|
2698
|
+
*/
|
|
2699
|
+
function encodeParamsForBody(xhr, elt, filteredParameters) {
|
|
2505
2700
|
let encodedParameters = null
|
|
2506
|
-
withExtensions(elt, function
|
|
2701
|
+
withExtensions(elt, function(extension) {
|
|
2507
2702
|
if (encodedParameters == null) {
|
|
2508
2703
|
encodedParameters = extension.encodeParameters(xhr, filteredParameters, elt)
|
|
2509
2704
|
}
|
|
@@ -2512,7 +2707,7 @@ const htmx = (function () {
|
|
|
2512
2707
|
return encodedParameters
|
|
2513
2708
|
} else {
|
|
2514
2709
|
if (usesFormData(elt)) {
|
|
2515
|
-
return
|
|
2710
|
+
return formDataFromObject(filteredParameters)
|
|
2516
2711
|
} else {
|
|
2517
2712
|
return urlEncode(filteredParameters)
|
|
2518
2713
|
}
|
|
@@ -2524,11 +2719,11 @@ const htmx = (function () {
|
|
|
2524
2719
|
* @param {Element} target
|
|
2525
2720
|
* @returns {import("./htmx").HtmxSettleInfo}
|
|
2526
2721
|
*/
|
|
2527
|
-
function makeSettleInfo
|
|
2722
|
+
function makeSettleInfo(target) {
|
|
2528
2723
|
return { tasks: [], elts: [target] }
|
|
2529
2724
|
}
|
|
2530
2725
|
|
|
2531
|
-
function updateScrollState
|
|
2726
|
+
function updateScrollState(content, swapSpec) {
|
|
2532
2727
|
const first = content[0]
|
|
2533
2728
|
const last = content[content.length - 1]
|
|
2534
2729
|
if (swapSpec.scroll) {
|
|
@@ -2572,7 +2767,7 @@ const htmx = (function () {
|
|
|
2572
2767
|
* @param {Object=} values
|
|
2573
2768
|
* @returns {Object}
|
|
2574
2769
|
*/
|
|
2575
|
-
function getValuesForElement
|
|
2770
|
+
function getValuesForElement(elt, attr, evalAsDefault, values) {
|
|
2576
2771
|
if (values == null) {
|
|
2577
2772
|
values = {}
|
|
2578
2773
|
}
|
|
@@ -2598,7 +2793,7 @@ const htmx = (function () {
|
|
|
2598
2793
|
}
|
|
2599
2794
|
let varsValues
|
|
2600
2795
|
if (evaluateValue) {
|
|
2601
|
-
varsValues = maybeEval(elt, function
|
|
2796
|
+
varsValues = maybeEval(elt, function() { return Function('return (' + str + ')')() }, {})
|
|
2602
2797
|
} else {
|
|
2603
2798
|
varsValues = parseJSON(str)
|
|
2604
2799
|
}
|
|
@@ -2613,7 +2808,7 @@ const htmx = (function () {
|
|
|
2613
2808
|
return getValuesForElement(parentElt(elt), attr, evalAsDefault, values)
|
|
2614
2809
|
}
|
|
2615
2810
|
|
|
2616
|
-
function maybeEval
|
|
2811
|
+
function maybeEval(elt, toEval, defaultVal) {
|
|
2617
2812
|
if (htmx.config.allowEval) {
|
|
2618
2813
|
return toEval()
|
|
2619
2814
|
} else {
|
|
@@ -2624,31 +2819,31 @@ const htmx = (function () {
|
|
|
2624
2819
|
|
|
2625
2820
|
/**
|
|
2626
2821
|
* @param {HTMLElement} elt
|
|
2627
|
-
* @param {
|
|
2822
|
+
* @param {*?} expressionVars
|
|
2628
2823
|
* @returns
|
|
2629
2824
|
*/
|
|
2630
|
-
function getHXVarsForElement
|
|
2825
|
+
function getHXVarsForElement(elt, expressionVars) {
|
|
2631
2826
|
return getValuesForElement(elt, 'hx-vars', true, expressionVars)
|
|
2632
2827
|
}
|
|
2633
2828
|
|
|
2634
2829
|
/**
|
|
2635
2830
|
* @param {HTMLElement} elt
|
|
2636
|
-
* @param {
|
|
2831
|
+
* @param {*?} expressionVars
|
|
2637
2832
|
* @returns
|
|
2638
2833
|
*/
|
|
2639
|
-
function getHXValsForElement
|
|
2834
|
+
function getHXValsForElement(elt, expressionVars) {
|
|
2640
2835
|
return getValuesForElement(elt, 'hx-vals', false, expressionVars)
|
|
2641
2836
|
}
|
|
2642
2837
|
|
|
2643
2838
|
/**
|
|
2644
2839
|
* @param {HTMLElement} elt
|
|
2645
|
-
* @returns {
|
|
2840
|
+
* @returns {FormData}
|
|
2646
2841
|
*/
|
|
2647
|
-
function getExpressionVars
|
|
2648
|
-
return mergeObjects(getHXVarsForElement(elt), getHXValsForElement(elt))
|
|
2842
|
+
function getExpressionVars(elt) {
|
|
2843
|
+
return formDataFromObject(mergeObjects(getHXVarsForElement(elt), getHXValsForElement(elt)))
|
|
2649
2844
|
}
|
|
2650
2845
|
|
|
2651
|
-
function safelySetHeaderValue
|
|
2846
|
+
function safelySetHeaderValue(xhr, header, headerValue) {
|
|
2652
2847
|
if (headerValue !== null) {
|
|
2653
2848
|
try {
|
|
2654
2849
|
xhr.setRequestHeader(header, headerValue)
|
|
@@ -2660,7 +2855,7 @@ const htmx = (function () {
|
|
|
2660
2855
|
}
|
|
2661
2856
|
}
|
|
2662
2857
|
|
|
2663
|
-
function getPathFromResponse
|
|
2858
|
+
function getPathFromResponse(xhr) {
|
|
2664
2859
|
// NB: IE11 does not support this stuff
|
|
2665
2860
|
if (xhr.responseURL && typeof (URL) !== 'undefined') {
|
|
2666
2861
|
try {
|
|
@@ -2672,11 +2867,11 @@ const htmx = (function () {
|
|
|
2672
2867
|
}
|
|
2673
2868
|
}
|
|
2674
2869
|
|
|
2675
|
-
function hasHeader
|
|
2870
|
+
function hasHeader(xhr, regexp) {
|
|
2676
2871
|
return regexp.test(xhr.getAllResponseHeaders())
|
|
2677
2872
|
}
|
|
2678
2873
|
|
|
2679
|
-
function ajaxHelper
|
|
2874
|
+
function ajaxHelper(verb, path, context) {
|
|
2680
2875
|
verb = verb.toLowerCase()
|
|
2681
2876
|
if (context) {
|
|
2682
2877
|
if (context instanceof Element || isType(context, 'String')) {
|
|
@@ -2703,7 +2898,7 @@ const htmx = (function () {
|
|
|
2703
2898
|
}
|
|
2704
2899
|
}
|
|
2705
2900
|
|
|
2706
|
-
function hierarchyForElt
|
|
2901
|
+
function hierarchyForElt(elt) {
|
|
2707
2902
|
const arr = []
|
|
2708
2903
|
while (elt) {
|
|
2709
2904
|
arr.push(elt)
|
|
@@ -2712,7 +2907,7 @@ const htmx = (function () {
|
|
|
2712
2907
|
return arr
|
|
2713
2908
|
}
|
|
2714
2909
|
|
|
2715
|
-
function verifyPath
|
|
2910
|
+
function verifyPath(elt, path, requestConfig) {
|
|
2716
2911
|
let sameHost
|
|
2717
2912
|
let url
|
|
2718
2913
|
if (typeof URL === 'function') {
|
|
@@ -2733,12 +2928,128 @@ const htmx = (function () {
|
|
|
2733
2928
|
return triggerEvent(elt, 'htmx:validateUrl', mergeObjects({ url, sameHost }, requestConfig))
|
|
2734
2929
|
}
|
|
2735
2930
|
|
|
2736
|
-
function
|
|
2931
|
+
function formDataFromObject(obj) {
|
|
2932
|
+
if (obj instanceof FormData) return obj
|
|
2933
|
+
const formData = new FormData()
|
|
2934
|
+
for (const key in obj) {
|
|
2935
|
+
if (obj.hasOwnProperty(key)) {
|
|
2936
|
+
if (typeof obj[key].forEach === 'function') {
|
|
2937
|
+
obj[key].forEach(function(v) { formData.append(key, v) })
|
|
2938
|
+
} else if (typeof obj[key] === 'object') {
|
|
2939
|
+
formData.append(key, JSON.stringify(obj[key]))
|
|
2940
|
+
} else {
|
|
2941
|
+
formData.append(key, obj[key])
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
return formData
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2948
|
+
/**
|
|
2949
|
+
* @param {FormData} formData
|
|
2950
|
+
* @param {string|Symbol} name
|
|
2951
|
+
* @param {Array} array
|
|
2952
|
+
* @returns {Array}
|
|
2953
|
+
*/
|
|
2954
|
+
function formDataArrayProxy(formData, name, array) {
|
|
2955
|
+
// mutating the array should mutate the underlying form data
|
|
2956
|
+
return new Proxy(array, {
|
|
2957
|
+
get: function(target, key) {
|
|
2958
|
+
if (typeof key === 'number') return target[key]
|
|
2959
|
+
if (key === 'length') return target.length
|
|
2960
|
+
if (key === 'push') {
|
|
2961
|
+
return function(value) {
|
|
2962
|
+
target.push(value)
|
|
2963
|
+
formData.append(name, value)
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
if (typeof target[key] === 'function') {
|
|
2967
|
+
return function() {
|
|
2968
|
+
target[key].apply(target, arguments)
|
|
2969
|
+
formData.delete(name)
|
|
2970
|
+
target.forEach(function(v) { formData.append(name, v) })
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2974
|
+
if (target[key] && target[key].length === 1) {
|
|
2975
|
+
return target[key][0]
|
|
2976
|
+
} else {
|
|
2977
|
+
return target[key]
|
|
2978
|
+
}
|
|
2979
|
+
},
|
|
2980
|
+
set: function(target, index, value) {
|
|
2981
|
+
target[index] = value
|
|
2982
|
+
formData.delete(name)
|
|
2983
|
+
target.forEach(function(v) { formData.append(name, v) })
|
|
2984
|
+
return true
|
|
2985
|
+
}
|
|
2986
|
+
})
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2989
|
+
/**
|
|
2990
|
+
* @param {FormData} formData
|
|
2991
|
+
* @returns {Object}
|
|
2992
|
+
*/
|
|
2993
|
+
function formDataProxy(formData) {
|
|
2994
|
+
return new Proxy(formData, {
|
|
2995
|
+
get: function(target, name) {
|
|
2996
|
+
if (typeof name === 'symbol') {
|
|
2997
|
+
// Forward symbol calls to the FormData itself directly
|
|
2998
|
+
return Reflect.get(...arguments)
|
|
2999
|
+
}
|
|
3000
|
+
if (name === 'toJSON') {
|
|
3001
|
+
// Support JSON.stringify call on proxy
|
|
3002
|
+
return () => Object.fromEntries(formData)
|
|
3003
|
+
}
|
|
3004
|
+
if (name in target) {
|
|
3005
|
+
// Wrap in function with apply to correctly bind the FormData context, as a direct call would result in an illegal invocation error
|
|
3006
|
+
if (typeof target[name] === 'function') {
|
|
3007
|
+
return function() {
|
|
3008
|
+
return formData[name].apply(formData, arguments)
|
|
3009
|
+
}
|
|
3010
|
+
} else {
|
|
3011
|
+
return target[name]
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
const array = formData.getAll(name)
|
|
3015
|
+
// Those 2 undefined & single value returns are for retro-compatibility as we weren't using FormData before
|
|
3016
|
+
if (array.length === 0) {
|
|
3017
|
+
return undefined
|
|
3018
|
+
} else if (array.length === 1) {
|
|
3019
|
+
return array[0]
|
|
3020
|
+
} else {
|
|
3021
|
+
return formDataArrayProxy(target, name, array)
|
|
3022
|
+
}
|
|
3023
|
+
},
|
|
3024
|
+
set: function(target, name, value) {
|
|
3025
|
+
target.delete(name)
|
|
3026
|
+
if (typeof value.forEach === 'function') {
|
|
3027
|
+
value.forEach(function(v) { target.append(name, v) })
|
|
3028
|
+
} else {
|
|
3029
|
+
target.append(name, value)
|
|
3030
|
+
}
|
|
3031
|
+
return true
|
|
3032
|
+
},
|
|
3033
|
+
deleteProperty: function(target, name) {
|
|
3034
|
+
target.delete(name)
|
|
3035
|
+
return true
|
|
3036
|
+
},
|
|
3037
|
+
// Support Object.assign call from proxy
|
|
3038
|
+
ownKeys: function(target) {
|
|
3039
|
+
return Reflect.ownKeys(Object.fromEntries(target))
|
|
3040
|
+
},
|
|
3041
|
+
getOwnPropertyDescriptor: function(target, prop) {
|
|
3042
|
+
return Reflect.getOwnPropertyDescriptor(Object.fromEntries(target), prop)
|
|
3043
|
+
}
|
|
3044
|
+
})
|
|
3045
|
+
}
|
|
3046
|
+
|
|
3047
|
+
function issueAjaxRequest(verb, path, elt, event, etc, confirmed) {
|
|
2737
3048
|
let resolve = null
|
|
2738
3049
|
let reject = null
|
|
2739
3050
|
etc = etc != null ? etc : {}
|
|
2740
3051
|
if (etc.returnPromise && typeof Promise !== 'undefined') {
|
|
2741
|
-
var promise = new Promise(function
|
|
3052
|
+
var promise = new Promise(function(_resolve, _reject) {
|
|
2742
3053
|
resolve = _resolve
|
|
2743
3054
|
reject = _reject
|
|
2744
3055
|
})
|
|
@@ -2782,7 +3093,7 @@ const htmx = (function () {
|
|
|
2782
3093
|
const confirmQuestion = getClosestAttributeValue(elt, 'hx-confirm')
|
|
2783
3094
|
// allow event-based confirmation w/ a callback
|
|
2784
3095
|
if (confirmed === undefined) {
|
|
2785
|
-
const issueRequest = function
|
|
3096
|
+
const issueRequest = function(skipConfirmation) {
|
|
2786
3097
|
return issueAjaxRequest(verb, path, elt, event, etc, !!skipConfirmation)
|
|
2787
3098
|
}
|
|
2788
3099
|
const confirmDetails = { target, elt, path, verb, triggeringEvent: event, etc, issueRequest, question: confirmQuestion }
|
|
@@ -2844,16 +3155,16 @@ const htmx = (function () {
|
|
|
2844
3155
|
eltData.queuedRequests = []
|
|
2845
3156
|
}
|
|
2846
3157
|
if (queueStrategy === 'first' && eltData.queuedRequests.length === 0) {
|
|
2847
|
-
eltData.queuedRequests.push(function
|
|
3158
|
+
eltData.queuedRequests.push(function() {
|
|
2848
3159
|
issueAjaxRequest(verb, path, elt, event, etc)
|
|
2849
3160
|
})
|
|
2850
3161
|
} else if (queueStrategy === 'all') {
|
|
2851
|
-
eltData.queuedRequests.push(function
|
|
3162
|
+
eltData.queuedRequests.push(function() {
|
|
2852
3163
|
issueAjaxRequest(verb, path, elt, event, etc)
|
|
2853
3164
|
})
|
|
2854
3165
|
} else if (queueStrategy === 'last') {
|
|
2855
3166
|
eltData.queuedRequests = [] // dump existing queue
|
|
2856
|
-
eltData.queuedRequests.push(function
|
|
3167
|
+
eltData.queuedRequests.push(function() {
|
|
2857
3168
|
issueAjaxRequest(verb, path, elt, event, etc)
|
|
2858
3169
|
})
|
|
2859
3170
|
}
|
|
@@ -2865,7 +3176,7 @@ const htmx = (function () {
|
|
|
2865
3176
|
const xhr = new XMLHttpRequest()
|
|
2866
3177
|
eltData.xhr = xhr
|
|
2867
3178
|
eltData.abortable = abortable
|
|
2868
|
-
const endRequestLock = function
|
|
3179
|
+
const endRequestLock = function() {
|
|
2869
3180
|
eltData.xhr = null
|
|
2870
3181
|
eltData.abortable = false
|
|
2871
3182
|
if (eltData.queuedRequests != null &&
|
|
@@ -2905,16 +3216,16 @@ const htmx = (function () {
|
|
|
2905
3216
|
}
|
|
2906
3217
|
const results = getInputValues(elt, verb)
|
|
2907
3218
|
let errors = results.errors
|
|
2908
|
-
|
|
3219
|
+
const rawFormData = results.formData
|
|
2909
3220
|
if (etc.values) {
|
|
2910
|
-
|
|
3221
|
+
overrideFormData(rawFormData, formDataFromObject(etc.values))
|
|
2911
3222
|
}
|
|
2912
3223
|
const expressionVars = getExpressionVars(elt)
|
|
2913
|
-
const
|
|
2914
|
-
let
|
|
3224
|
+
const allFormData = overrideFormData(rawFormData, expressionVars)
|
|
3225
|
+
let filteredFormData = filterValues(allFormData, elt)
|
|
2915
3226
|
|
|
2916
3227
|
if (htmx.config.getCacheBusterParam && verb === 'get') {
|
|
2917
|
-
|
|
3228
|
+
filteredFormData.set('org.htmx.cache-buster', getRawAttribute(target, 'id') || 'true')
|
|
2918
3229
|
}
|
|
2919
3230
|
|
|
2920
3231
|
// behavior of anchors w/ empty href is to use the current URL
|
|
@@ -2931,8 +3242,10 @@ const htmx = (function () {
|
|
|
2931
3242
|
const requestConfig = {
|
|
2932
3243
|
boosted: eltIsBoosted,
|
|
2933
3244
|
useUrlParams,
|
|
2934
|
-
|
|
2935
|
-
|
|
3245
|
+
formData: filteredFormData,
|
|
3246
|
+
parameters: formDataProxy(filteredFormData),
|
|
3247
|
+
unfilteredFormData: allFormData,
|
|
3248
|
+
unfilteredParameters: formDataProxy(allFormData),
|
|
2936
3249
|
headers,
|
|
2937
3250
|
target,
|
|
2938
3251
|
verb,
|
|
@@ -2953,7 +3266,7 @@ const htmx = (function () {
|
|
|
2953
3266
|
path = requestConfig.path
|
|
2954
3267
|
verb = requestConfig.verb
|
|
2955
3268
|
headers = requestConfig.headers
|
|
2956
|
-
|
|
3269
|
+
filteredFormData = formDataFromObject(requestConfig.parameters)
|
|
2957
3270
|
errors = requestConfig.errors
|
|
2958
3271
|
useUrlParams = requestConfig.useUrlParams
|
|
2959
3272
|
|
|
@@ -2971,14 +3284,14 @@ const htmx = (function () {
|
|
|
2971
3284
|
let finalPath = path
|
|
2972
3285
|
if (useUrlParams) {
|
|
2973
3286
|
finalPath = pathNoAnchor
|
|
2974
|
-
const
|
|
2975
|
-
if (
|
|
3287
|
+
const hasValues = !filteredFormData.keys().next().done
|
|
3288
|
+
if (hasValues) {
|
|
2976
3289
|
if (finalPath.indexOf('?') < 0) {
|
|
2977
3290
|
finalPath += '?'
|
|
2978
3291
|
} else {
|
|
2979
3292
|
finalPath += '&'
|
|
2980
3293
|
}
|
|
2981
|
-
finalPath += urlEncode(
|
|
3294
|
+
finalPath += urlEncode(filteredFormData)
|
|
2982
3295
|
if (anchor) {
|
|
2983
3296
|
finalPath += '#' + anchor
|
|
2984
3297
|
}
|
|
@@ -3022,7 +3335,7 @@ const htmx = (function () {
|
|
|
3022
3335
|
}
|
|
3023
3336
|
}
|
|
3024
3337
|
|
|
3025
|
-
xhr.onload = function
|
|
3338
|
+
xhr.onload = function() {
|
|
3026
3339
|
try {
|
|
3027
3340
|
const hierarchy = hierarchyForElt(elt)
|
|
3028
3341
|
responseInfo.pathInfo.responsePath = getPathFromResponse(xhr)
|
|
@@ -3052,21 +3365,21 @@ const htmx = (function () {
|
|
|
3052
3365
|
throw e
|
|
3053
3366
|
}
|
|
3054
3367
|
}
|
|
3055
|
-
xhr.onerror = function
|
|
3368
|
+
xhr.onerror = function() {
|
|
3056
3369
|
removeRequestIndicators(indicators, disableElts)
|
|
3057
3370
|
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo)
|
|
3058
3371
|
triggerErrorEvent(elt, 'htmx:sendError', responseInfo)
|
|
3059
3372
|
maybeCall(reject)
|
|
3060
3373
|
endRequestLock()
|
|
3061
3374
|
}
|
|
3062
|
-
xhr.onabort = function
|
|
3375
|
+
xhr.onabort = function() {
|
|
3063
3376
|
removeRequestIndicators(indicators, disableElts)
|
|
3064
3377
|
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo)
|
|
3065
3378
|
triggerErrorEvent(elt, 'htmx:sendAbort', responseInfo)
|
|
3066
3379
|
maybeCall(reject)
|
|
3067
3380
|
endRequestLock()
|
|
3068
3381
|
}
|
|
3069
|
-
xhr.ontimeout = function
|
|
3382
|
+
xhr.ontimeout = function() {
|
|
3070
3383
|
removeRequestIndicators(indicators, disableElts)
|
|
3071
3384
|
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo)
|
|
3072
3385
|
triggerErrorEvent(elt, 'htmx:timeout', responseInfo)
|
|
@@ -3081,9 +3394,9 @@ const htmx = (function () {
|
|
|
3081
3394
|
var indicators = addRequestIndicatorClasses(elt)
|
|
3082
3395
|
var disableElts = disableElements(elt)
|
|
3083
3396
|
|
|
3084
|
-
forEach(['loadstart', 'loadend', 'progress', 'abort'], function
|
|
3085
|
-
forEach([xhr, xhr.upload], function
|
|
3086
|
-
target.addEventListener(eventName, function
|
|
3397
|
+
forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) {
|
|
3398
|
+
forEach([xhr, xhr.upload], function(target) {
|
|
3399
|
+
target.addEventListener(eventName, function(event) {
|
|
3087
3400
|
triggerEvent(elt, 'htmx:xhr:' + eventName, {
|
|
3088
3401
|
lengthComputable: event.lengthComputable,
|
|
3089
3402
|
loaded: event.loaded,
|
|
@@ -3093,12 +3406,12 @@ const htmx = (function () {
|
|
|
3093
3406
|
})
|
|
3094
3407
|
})
|
|
3095
3408
|
triggerEvent(elt, 'htmx:beforeSend', responseInfo)
|
|
3096
|
-
const params = useUrlParams ? null : encodeParamsForBody(xhr, elt,
|
|
3409
|
+
const params = useUrlParams ? null : encodeParamsForBody(xhr, elt, filteredFormData)
|
|
3097
3410
|
xhr.send(params)
|
|
3098
3411
|
return promise
|
|
3099
3412
|
}
|
|
3100
3413
|
|
|
3101
|
-
function determineHistoryUpdates
|
|
3414
|
+
function determineHistoryUpdates(elt, responseInfo) {
|
|
3102
3415
|
const xhr = responseInfo.xhr
|
|
3103
3416
|
|
|
3104
3417
|
//= ==========================================
|
|
@@ -3165,8 +3478,7 @@ const htmx = (function () {
|
|
|
3165
3478
|
}
|
|
3166
3479
|
|
|
3167
3480
|
// restore any anchor associated with the request
|
|
3168
|
-
if (responseInfo.pathInfo.anchor &&
|
|
3169
|
-
path.indexOf('#') === -1) {
|
|
3481
|
+
if (responseInfo.pathInfo.anchor && path.indexOf('#') === -1) {
|
|
3170
3482
|
path = path + '#' + responseInfo.pathInfo.anchor
|
|
3171
3483
|
}
|
|
3172
3484
|
|
|
@@ -3179,17 +3491,45 @@ const htmx = (function () {
|
|
|
3179
3491
|
}
|
|
3180
3492
|
}
|
|
3181
3493
|
|
|
3182
|
-
function
|
|
3494
|
+
function codeMatches(responseHandlingConfig, status) {
|
|
3495
|
+
var regExp = new RegExp(responseHandlingConfig.code)
|
|
3496
|
+
return regExp.test(status)
|
|
3497
|
+
}
|
|
3498
|
+
|
|
3499
|
+
function resolveResponseHandling(xhr) {
|
|
3500
|
+
for (var i = 0; i < htmx.config.responseHandling.length; i++) {
|
|
3501
|
+
var responseHandlingElement = htmx.config.responseHandling[i]
|
|
3502
|
+
if (codeMatches(responseHandlingElement, xhr.status)) {
|
|
3503
|
+
return responseHandlingElement
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
// no matches, return no swap
|
|
3507
|
+
return {
|
|
3508
|
+
swap: false
|
|
3509
|
+
}
|
|
3510
|
+
}
|
|
3511
|
+
|
|
3512
|
+
function handleTitle(title) {
|
|
3513
|
+
if (title) {
|
|
3514
|
+
const titleElt = find('title')
|
|
3515
|
+
if (titleElt) {
|
|
3516
|
+
titleElt.innerHTML = title
|
|
3517
|
+
} else {
|
|
3518
|
+
window.document.title = title
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
|
|
3523
|
+
function handleAjaxResponse(elt, responseInfo) {
|
|
3183
3524
|
const xhr = responseInfo.xhr
|
|
3184
3525
|
let target = responseInfo.target
|
|
3185
3526
|
const etc = responseInfo.etc
|
|
3186
|
-
const
|
|
3187
|
-
const select = responseInfo.select
|
|
3527
|
+
const responseInfoSelect = responseInfo.select
|
|
3188
3528
|
|
|
3189
3529
|
if (!triggerEvent(elt, 'htmx:beforeOnLoad', responseInfo)) return
|
|
3190
3530
|
|
|
3191
3531
|
if (hasHeader(xhr, /HX-Trigger:/i)) {
|
|
3192
|
-
|
|
3532
|
+
handleTriggerHeader(xhr, 'HX-Trigger', elt)
|
|
3193
3533
|
}
|
|
3194
3534
|
|
|
3195
3535
|
if (hasHeader(xhr, /HX-Location:/i)) {
|
|
@@ -3202,7 +3542,7 @@ const htmx = (function () {
|
|
|
3202
3542
|
redirectPath = swapSpec.path
|
|
3203
3543
|
delete swapSpec.path
|
|
3204
3544
|
}
|
|
3205
|
-
ajaxHelper('GET', redirectPath, swapSpec).then(function
|
|
3545
|
+
ajaxHelper('GET', redirectPath, swapSpec).then(function() {
|
|
3206
3546
|
pushUrlIntoHistory(redirectPath)
|
|
3207
3547
|
})
|
|
3208
3548
|
return
|
|
@@ -3231,21 +3571,49 @@ const htmx = (function () {
|
|
|
3231
3571
|
|
|
3232
3572
|
const historyUpdate = determineHistoryUpdates(elt, responseInfo)
|
|
3233
3573
|
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3574
|
+
const responseHandling = resolveResponseHandling(xhr)
|
|
3575
|
+
const shouldSwap = responseHandling.swap
|
|
3576
|
+
let isError = !!responseHandling.error
|
|
3577
|
+
let ignoreTitle = htmx.config.ignoreTitle || responseHandling.ignoreTitle
|
|
3578
|
+
let selectOverride = responseHandling.select
|
|
3579
|
+
if (responseHandling.target) {
|
|
3580
|
+
responseInfo.target = querySelectorExt(elt, responseHandling.target)
|
|
3581
|
+
}
|
|
3582
|
+
var swapOverride = etc.swapOverride
|
|
3583
|
+
if (swapOverride == null && responseHandling.swapOverride) {
|
|
3584
|
+
swapOverride = responseHandling.swapOverride
|
|
3585
|
+
}
|
|
3586
|
+
|
|
3587
|
+
// response headers override response handling config
|
|
3588
|
+
if (hasHeader(xhr, /HX-Retarget:/i)) {
|
|
3589
|
+
if (xhr.getResponseHeader('HX-Retarget') === 'this') {
|
|
3590
|
+
responseInfo.target = elt
|
|
3591
|
+
} else {
|
|
3592
|
+
responseInfo.target = querySelectorExt(elt, xhr.getResponseHeader('HX-Retarget'))
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
if (hasHeader(xhr, /HX-Reswap:/i)) {
|
|
3596
|
+
swapOverride = xhr.getResponseHeader('HX-Reswap')
|
|
3597
|
+
}
|
|
3598
|
+
|
|
3599
|
+
var serverResponse = xhr.response
|
|
3600
|
+
var beforeSwapDetails = mergeObjects({
|
|
3601
|
+
shouldSwap,
|
|
3602
|
+
serverResponse,
|
|
3603
|
+
isError,
|
|
3604
|
+
ignoreTitle,
|
|
3605
|
+
selectOverride
|
|
3606
|
+
}, responseInfo)
|
|
3607
|
+
|
|
3608
|
+
if (responseHandling.event && !triggerEvent(target, responseHandling.event, beforeSwapDetails)) return
|
|
3609
|
+
|
|
3243
3610
|
if (!triggerEvent(target, 'htmx:beforeSwap', beforeSwapDetails)) return
|
|
3244
3611
|
|
|
3245
3612
|
target = beforeSwapDetails.target // allow re-targeting
|
|
3246
3613
|
serverResponse = beforeSwapDetails.serverResponse // allow updating content
|
|
3247
3614
|
isError = beforeSwapDetails.isError // allow updating error
|
|
3248
3615
|
ignoreTitle = beforeSwapDetails.ignoreTitle // allow updating ignoring title
|
|
3616
|
+
selectOverride = beforeSwapDetails.selectOverride // allow updating select override
|
|
3249
3617
|
|
|
3250
3618
|
responseInfo.target = target // Make updated target available to response events
|
|
3251
3619
|
responseInfo.failed = isError // Make failed property available to response events
|
|
@@ -3256,7 +3624,7 @@ const htmx = (function () {
|
|
|
3256
3624
|
cancelPolling(elt)
|
|
3257
3625
|
}
|
|
3258
3626
|
|
|
3259
|
-
withExtensions(elt, function
|
|
3627
|
+
withExtensions(elt, function(extension) {
|
|
3260
3628
|
serverResponse = extension.transformResponse(serverResponse, xhr, elt)
|
|
3261
3629
|
})
|
|
3262
3630
|
|
|
@@ -3265,14 +3633,13 @@ const htmx = (function () {
|
|
|
3265
3633
|
saveCurrentPageToHistory()
|
|
3266
3634
|
}
|
|
3267
3635
|
|
|
3268
|
-
let swapOverride = etc.swapOverride
|
|
3269
3636
|
if (hasHeader(xhr, /HX-Reswap:/i)) {
|
|
3270
3637
|
swapOverride = xhr.getResponseHeader('HX-Reswap')
|
|
3271
3638
|
}
|
|
3272
3639
|
var swapSpec = getSwapSpecification(elt, swapOverride)
|
|
3273
3640
|
|
|
3274
|
-
if (swapSpec.hasOwnProperty('ignoreTitle')) {
|
|
3275
|
-
ignoreTitle =
|
|
3641
|
+
if (!swapSpec.hasOwnProperty('ignoreTitle')) {
|
|
3642
|
+
swapSpec.ignoreTitle = ignoreTitle
|
|
3276
3643
|
}
|
|
3277
3644
|
|
|
3278
3645
|
target.classList.add(htmx.config.swappingClass)
|
|
@@ -3281,31 +3648,19 @@ const htmx = (function () {
|
|
|
3281
3648
|
let settleResolve = null
|
|
3282
3649
|
let settleReject = null
|
|
3283
3650
|
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
let selectionInfo = {}
|
|
3288
|
-
try {
|
|
3289
|
-
selectionInfo = {
|
|
3290
|
-
elt: activeElt,
|
|
3291
|
-
// @ts-ignore
|
|
3292
|
-
start: activeElt ? activeElt.selectionStart : null,
|
|
3293
|
-
// @ts-ignore
|
|
3294
|
-
end: activeElt ? activeElt.selectionEnd : null
|
|
3295
|
-
}
|
|
3296
|
-
} catch (e) {
|
|
3297
|
-
// safari issue - see https://github.com/microsoft/playwright/issues/5894
|
|
3298
|
-
}
|
|
3651
|
+
if (responseInfoSelect) {
|
|
3652
|
+
selectOverride = responseInfoSelect
|
|
3653
|
+
}
|
|
3299
3654
|
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
}
|
|
3655
|
+
if (hasHeader(xhr, /HX-Reselect:/i)) {
|
|
3656
|
+
selectOverride = xhr.getResponseHeader('HX-Reselect')
|
|
3657
|
+
}
|
|
3304
3658
|
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
}
|
|
3659
|
+
const selectOOB = getClosestAttributeValue(elt, 'hx-select-oob')
|
|
3660
|
+
const select = getClosestAttributeValue(elt, 'hx-select')
|
|
3308
3661
|
|
|
3662
|
+
let doSwap = function() {
|
|
3663
|
+
try {
|
|
3309
3664
|
// if we need to save history, do so, before swapping so that relative resources have the correct base URL
|
|
3310
3665
|
if (historyUpdate.type) {
|
|
3311
3666
|
triggerEvent(getDocument().body, 'htmx:beforeHistoryUpdate', mergeObjects({ history: historyUpdate }, responseInfo))
|
|
@@ -3318,88 +3673,32 @@ const htmx = (function () {
|
|
|
3318
3673
|
}
|
|
3319
3674
|
}
|
|
3320
3675
|
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
// @ts-ignore
|
|
3333
|
-
try {
|
|
3334
|
-
newActiveElt.setSelectionRange(selectionInfo.start, selectionInfo.end)
|
|
3335
|
-
} catch (e) {
|
|
3336
|
-
// the setSelectionRange method is present on fields that don't support it, so just let this fail
|
|
3676
|
+
swap(target, serverResponse, swapSpec, {
|
|
3677
|
+
select: selectOverride || select,
|
|
3678
|
+
selectOOB,
|
|
3679
|
+
eventInfo: responseInfo,
|
|
3680
|
+
anchor: responseInfo.pathInfo.anchor,
|
|
3681
|
+
contextElement: elt,
|
|
3682
|
+
afterSwapCallback: function() {
|
|
3683
|
+
if (hasHeader(xhr, /HX-Trigger-After-Swap:/i)) {
|
|
3684
|
+
let finalElt = elt
|
|
3685
|
+
if (!bodyContains(elt)) {
|
|
3686
|
+
finalElt = getDocument().body
|
|
3337
3687
|
}
|
|
3688
|
+
handleTriggerHeader(xhr, 'HX-Trigger-After-Swap', finalElt)
|
|
3338
3689
|
}
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
}
|
|
3348
|
-
triggerEvent(elt, 'htmx:afterSwap', responseInfo)
|
|
3349
|
-
})
|
|
3350
|
-
|
|
3351
|
-
if (hasHeader(xhr, /HX-Trigger-After-Swap:/i)) {
|
|
3352
|
-
let finalElt = elt
|
|
3353
|
-
if (!bodyContains(elt)) {
|
|
3354
|
-
finalElt = getDocument().body
|
|
3355
|
-
}
|
|
3356
|
-
handleTrigger(xhr, 'HX-Trigger-After-Swap', finalElt)
|
|
3357
|
-
}
|
|
3358
|
-
|
|
3359
|
-
const doSettle = function () {
|
|
3360
|
-
forEach(settleInfo.tasks, function (task) {
|
|
3361
|
-
task.call()
|
|
3362
|
-
})
|
|
3363
|
-
forEach(settleInfo.elts, function (elt) {
|
|
3364
|
-
if (elt.classList) {
|
|
3365
|
-
elt.classList.remove(htmx.config.settlingClass)
|
|
3366
|
-
}
|
|
3367
|
-
triggerEvent(elt, 'htmx:afterSettle', responseInfo)
|
|
3368
|
-
})
|
|
3369
|
-
|
|
3370
|
-
if (responseInfo.pathInfo.anchor) {
|
|
3371
|
-
const anchorTarget = getDocument().getElementById(responseInfo.pathInfo.anchor)
|
|
3372
|
-
if (anchorTarget) {
|
|
3373
|
-
anchorTarget.scrollIntoView({ block: 'start', behavior: 'auto' })
|
|
3374
|
-
}
|
|
3375
|
-
}
|
|
3376
|
-
|
|
3377
|
-
if (settleInfo.title && !ignoreTitle) {
|
|
3378
|
-
const titleElt = find('title')
|
|
3379
|
-
if (titleElt) {
|
|
3380
|
-
titleElt.innerHTML = settleInfo.title
|
|
3381
|
-
} else {
|
|
3382
|
-
window.document.title = settleInfo.title
|
|
3383
|
-
}
|
|
3384
|
-
}
|
|
3385
|
-
|
|
3386
|
-
updateScrollState(settleInfo.elts, swapSpec)
|
|
3387
|
-
|
|
3388
|
-
if (hasHeader(xhr, /HX-Trigger-After-Settle:/i)) {
|
|
3389
|
-
let finalElt = elt
|
|
3390
|
-
if (!bodyContains(elt)) {
|
|
3391
|
-
finalElt = getDocument().body
|
|
3690
|
+
},
|
|
3691
|
+
afterSettleCallback: function() {
|
|
3692
|
+
if (hasHeader(xhr, /HX-Trigger-After-Settle:/i)) {
|
|
3693
|
+
let finalElt = elt
|
|
3694
|
+
if (!bodyContains(elt)) {
|
|
3695
|
+
finalElt = getDocument().body
|
|
3696
|
+
}
|
|
3697
|
+
handleTriggerHeader(xhr, 'HX-Trigger-After-Settle', finalElt)
|
|
3392
3698
|
}
|
|
3393
|
-
|
|
3699
|
+
maybeCall(settleResolve)
|
|
3394
3700
|
}
|
|
3395
|
-
|
|
3396
|
-
}
|
|
3397
|
-
|
|
3398
|
-
if (swapSpec.settleDelay > 0) {
|
|
3399
|
-
setTimeout(doSettle, swapSpec.settleDelay)
|
|
3400
|
-
} else {
|
|
3401
|
-
doSettle()
|
|
3402
|
-
}
|
|
3701
|
+
})
|
|
3403
3702
|
} catch (e) {
|
|
3404
3703
|
triggerErrorEvent(elt, 'htmx:swapError', responseInfo)
|
|
3405
3704
|
maybeCall(settleReject)
|
|
@@ -3413,16 +3712,16 @@ const htmx = (function () {
|
|
|
3413
3712
|
}
|
|
3414
3713
|
|
|
3415
3714
|
if (shouldTransition &&
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
const settlePromise = new Promise(function
|
|
3715
|
+
triggerEvent(elt, 'htmx:beforeTransition', responseInfo) &&
|
|
3716
|
+
typeof Promise !== 'undefined' && document.startViewTransition) {
|
|
3717
|
+
const settlePromise = new Promise(function(_resolve, _reject) {
|
|
3419
3718
|
settleResolve = _resolve
|
|
3420
3719
|
settleReject = _reject
|
|
3421
3720
|
})
|
|
3422
3721
|
// wrap the original doSwap() in a call to startViewTransition()
|
|
3423
3722
|
const innerDoSwap = doSwap
|
|
3424
|
-
doSwap = function
|
|
3425
|
-
document.startViewTransition(function
|
|
3723
|
+
doSwap = function() {
|
|
3724
|
+
document.startViewTransition(function() {
|
|
3426
3725
|
innerDoSwap()
|
|
3427
3726
|
return settlePromise
|
|
3428
3727
|
})
|
|
@@ -3451,14 +3750,14 @@ const htmx = (function () {
|
|
|
3451
3750
|
* extensionBase defines the default functions for all extensions.
|
|
3452
3751
|
* @returns {import("./htmx").HtmxExtension}
|
|
3453
3752
|
*/
|
|
3454
|
-
function extensionBase
|
|
3753
|
+
function extensionBase() {
|
|
3455
3754
|
return {
|
|
3456
|
-
init: function
|
|
3457
|
-
onEvent: function
|
|
3458
|
-
transformResponse: function
|
|
3459
|
-
isInlineSwap: function
|
|
3460
|
-
handleSwap: function
|
|
3461
|
-
encodeParameters: function
|
|
3755
|
+
init: function(api) { return null },
|
|
3756
|
+
onEvent: function(name, evt) { return true },
|
|
3757
|
+
transformResponse: function(text, xhr, elt) { return text },
|
|
3758
|
+
isInlineSwap: function(swapStyle) { return false },
|
|
3759
|
+
handleSwap: function(swapStyle, target, fragment, settleInfo) { return false },
|
|
3760
|
+
encodeParameters: function(xhr, parameters, elt) { return null }
|
|
3462
3761
|
}
|
|
3463
3762
|
}
|
|
3464
3763
|
|
|
@@ -3468,7 +3767,7 @@ const htmx = (function () {
|
|
|
3468
3767
|
* @param {string} name
|
|
3469
3768
|
* @param {import("./htmx").HtmxExtension} extension
|
|
3470
3769
|
*/
|
|
3471
|
-
function defineExtension
|
|
3770
|
+
function defineExtension(name, extension) {
|
|
3472
3771
|
if (extension.init) {
|
|
3473
3772
|
extension.init(internalAPI)
|
|
3474
3773
|
}
|
|
@@ -3480,7 +3779,7 @@ const htmx = (function () {
|
|
|
3480
3779
|
*
|
|
3481
3780
|
* @param {string} name
|
|
3482
3781
|
*/
|
|
3483
|
-
function removeExtension
|
|
3782
|
+
function removeExtension(name) {
|
|
3484
3783
|
delete extensions[name]
|
|
3485
3784
|
}
|
|
3486
3785
|
|
|
@@ -3491,19 +3790,19 @@ const htmx = (function () {
|
|
|
3491
3790
|
* @param {import("./htmx").HtmxExtension[]=} extensionsToReturn
|
|
3492
3791
|
* @param {import("./htmx").HtmxExtension[]=} extensionsToIgnore
|
|
3493
3792
|
*/
|
|
3494
|
-
function getExtensions
|
|
3495
|
-
if (elt == undefined) {
|
|
3496
|
-
return extensionsToReturn
|
|
3497
|
-
}
|
|
3793
|
+
function getExtensions(elt, extensionsToReturn, extensionsToIgnore) {
|
|
3498
3794
|
if (extensionsToReturn == undefined) {
|
|
3499
3795
|
extensionsToReturn = []
|
|
3500
3796
|
}
|
|
3797
|
+
if (elt == undefined) {
|
|
3798
|
+
return extensionsToReturn
|
|
3799
|
+
}
|
|
3501
3800
|
if (extensionsToIgnore == undefined) {
|
|
3502
3801
|
extensionsToIgnore = []
|
|
3503
3802
|
}
|
|
3504
3803
|
const extensionsForElement = getAttributeValue(elt, 'hx-ext')
|
|
3505
3804
|
if (extensionsForElement) {
|
|
3506
|
-
forEach(extensionsForElement.split(','), function
|
|
3805
|
+
forEach(extensionsForElement.split(','), function(extensionName) {
|
|
3507
3806
|
extensionName = extensionName.replace(/ /g, '')
|
|
3508
3807
|
if (extensionName.slice(0, 7) == 'ignore:') {
|
|
3509
3808
|
extensionsToIgnore.push(extensionName.slice(7))
|
|
@@ -3523,37 +3822,29 @@ const htmx = (function () {
|
|
|
3523
3822
|
//= ===================================================================
|
|
3524
3823
|
// Initialization
|
|
3525
3824
|
//= ===================================================================
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
*/
|
|
3531
|
-
function ready (functionToCall) {
|
|
3532
|
-
// call the function exactly once no matter how many times this is called
|
|
3533
|
-
const callReadyFunction = function () {
|
|
3534
|
-
if (!functionToCall) return
|
|
3535
|
-
functionToCall()
|
|
3536
|
-
functionToCall = null
|
|
3537
|
-
}
|
|
3825
|
+
var isReady = false
|
|
3826
|
+
getDocument().addEventListener('DOMContentLoaded', function() {
|
|
3827
|
+
isReady = true
|
|
3828
|
+
})
|
|
3538
3829
|
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3830
|
+
/**
|
|
3831
|
+
* Execute a function now if DOMContentLoaded has fired, otherwise listen for it.
|
|
3832
|
+
*
|
|
3833
|
+
* This function uses isReady because there is no realiable way to ask the browswer whether
|
|
3834
|
+
* the DOMContentLoaded event has already been fired; there's a gap between DOMContentLoaded
|
|
3835
|
+
* firing and readystate=complete.
|
|
3836
|
+
*/
|
|
3837
|
+
function ready(fn) {
|
|
3838
|
+
// Checking readyState here is a failsafe in case the htmx script tag entered the DOM by
|
|
3839
|
+
// some means other than the initial page load.
|
|
3840
|
+
if (isReady || getDocument().readyState === 'complete') {
|
|
3841
|
+
fn()
|
|
3542
3842
|
} else {
|
|
3543
|
-
|
|
3544
|
-
* the next DOMContentLoaded or readystatechange event
|
|
3545
|
-
*/
|
|
3546
|
-
getDocument().addEventListener('DOMContentLoaded', function () {
|
|
3547
|
-
callReadyFunction()
|
|
3548
|
-
})
|
|
3549
|
-
getDocument().addEventListener('readystatechange', function () {
|
|
3550
|
-
if (getDocument().readyState !== 'complete') return
|
|
3551
|
-
callReadyFunction()
|
|
3552
|
-
})
|
|
3843
|
+
getDocument().addEventListener('DOMContentLoaded', fn)
|
|
3553
3844
|
}
|
|
3554
3845
|
}
|
|
3555
3846
|
|
|
3556
|
-
function insertIndicatorStyles
|
|
3847
|
+
function insertIndicatorStyles() {
|
|
3557
3848
|
if (htmx.config.includeIndicatorStyles !== false) {
|
|
3558
3849
|
getDocument().head.insertAdjacentHTML('beforeend',
|
|
3559
3850
|
'<style>\
|
|
@@ -3564,7 +3855,7 @@ const htmx = (function () {
|
|
|
3564
3855
|
}
|
|
3565
3856
|
}
|
|
3566
3857
|
|
|
3567
|
-
function getMetaConfig
|
|
3858
|
+
function getMetaConfig() {
|
|
3568
3859
|
const element = getDocument().querySelector('meta[name="htmx-config"]')
|
|
3569
3860
|
if (element) {
|
|
3570
3861
|
// @ts-ignore
|
|
@@ -3574,7 +3865,7 @@ const htmx = (function () {
|
|
|
3574
3865
|
}
|
|
3575
3866
|
}
|
|
3576
3867
|
|
|
3577
|
-
function mergeMetaConfig
|
|
3868
|
+
function mergeMetaConfig() {
|
|
3578
3869
|
const metaConfig = getMetaConfig()
|
|
3579
3870
|
if (metaConfig) {
|
|
3580
3871
|
htmx.config = mergeObjects(htmx.config, metaConfig)
|
|
@@ -3582,7 +3873,7 @@ const htmx = (function () {
|
|
|
3582
3873
|
}
|
|
3583
3874
|
|
|
3584
3875
|
// initialize the document
|
|
3585
|
-
ready(function
|
|
3876
|
+
ready(function() {
|
|
3586
3877
|
mergeMetaConfig()
|
|
3587
3878
|
insertIndicatorStyles()
|
|
3588
3879
|
let body = getDocument().body
|
|
@@ -3590,7 +3881,7 @@ const htmx = (function () {
|
|
|
3590
3881
|
const restoredElts = getDocument().querySelectorAll(
|
|
3591
3882
|
"[hx-trigger='restored'],[data-hx-trigger='restored']"
|
|
3592
3883
|
)
|
|
3593
|
-
body.addEventListener('htmx:abort', function
|
|
3884
|
+
body.addEventListener('htmx:abort', function(evt) {
|
|
3594
3885
|
const target = evt.target
|
|
3595
3886
|
const internalData = getInternalData(target)
|
|
3596
3887
|
if (internalData && internalData.xhr) {
|
|
@@ -3600,10 +3891,10 @@ const htmx = (function () {
|
|
|
3600
3891
|
/** @type {(ev: PopStateEvent) => any} */
|
|
3601
3892
|
const originalPopstate = window.onpopstate ? window.onpopstate.bind(window) : null
|
|
3602
3893
|
/** @type {(ev: PopStateEvent) => any} */
|
|
3603
|
-
window.onpopstate = function
|
|
3894
|
+
window.onpopstate = function(event) {
|
|
3604
3895
|
if (event.state && event.state.htmx) {
|
|
3605
3896
|
restoreHistory()
|
|
3606
|
-
forEach(restoredElts, function
|
|
3897
|
+
forEach(restoredElts, function(elt) {
|
|
3607
3898
|
triggerEvent(elt, 'htmx:restored', {
|
|
3608
3899
|
document: getDocument(),
|
|
3609
3900
|
triggerEvent
|
|
@@ -3615,12 +3906,11 @@ const htmx = (function () {
|
|
|
3615
3906
|
}
|
|
3616
3907
|
}
|
|
3617
3908
|
}
|
|
3618
|
-
setTimeout(function
|
|
3909
|
+
setTimeout(function() {
|
|
3619
3910
|
triggerEvent(body, 'htmx:load', {}) // give ready handlers a chance to load up before firing this event
|
|
3620
3911
|
body = null // kill reference for gc
|
|
3621
3912
|
}, 0)
|
|
3622
3913
|
})
|
|
3623
3914
|
|
|
3624
3915
|
return htmx
|
|
3625
|
-
}
|
|
3626
|
-
)()
|
|
3916
|
+
})()
|