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