plain.htmx 0.0.0__py3-none-any.whl

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.
Files changed (47) hide show
  1. plain/htmx/README.md +408 -0
  2. plain/htmx/__init__.py +0 -0
  3. plain/htmx/assets/htmx/htmx.js +3905 -0
  4. plain/htmx/assets/htmx/htmx.min.js +1 -0
  5. plain/htmx/assets/htmx/idiomorph/idiomorph-ext.js +872 -0
  6. plain/htmx/assets/htmx/idiomorph/idiomorph-ext.min.js +1 -0
  7. plain/htmx/assets/htmx/idiomorph/idiomorph-htmx.js +24 -0
  8. plain/htmx/assets/htmx/idiomorph/idiomorph.amd.js +852 -0
  9. plain/htmx/assets/htmx/idiomorph/idiomorph.cjs.js +850 -0
  10. plain/htmx/assets/htmx/idiomorph/idiomorph.esm.js +850 -0
  11. plain/htmx/assets/htmx/idiomorph/idiomorph.js +848 -0
  12. plain/htmx/assets/htmx/idiomorph/idiomorph.min.js +1 -0
  13. plain/htmx/assets/htmx/plainhtmx.js +56 -0
  14. plain/htmx/assets/htmx/src/ext/ajax-header.js +7 -0
  15. plain/htmx/assets/htmx/src/ext/alpine-morph.js +16 -0
  16. plain/htmx/assets/htmx/src/ext/class-tools.js +92 -0
  17. plain/htmx/assets/htmx/src/ext/client-side-templates.js +96 -0
  18. plain/htmx/assets/htmx/src/ext/debug.js +11 -0
  19. plain/htmx/assets/htmx/src/ext/disable-element.js +18 -0
  20. plain/htmx/assets/htmx/src/ext/event-header.js +37 -0
  21. plain/htmx/assets/htmx/src/ext/head-support.js +141 -0
  22. plain/htmx/assets/htmx/src/ext/include-vals.js +24 -0
  23. plain/htmx/assets/htmx/src/ext/json-enc.js +12 -0
  24. plain/htmx/assets/htmx/src/ext/loading-states.js +183 -0
  25. plain/htmx/assets/htmx/src/ext/method-override.js +11 -0
  26. plain/htmx/assets/htmx/src/ext/morphdom-swap.js +17 -0
  27. plain/htmx/assets/htmx/src/ext/multi-swap.js +45 -0
  28. plain/htmx/assets/htmx/src/ext/path-deps.js +60 -0
  29. plain/htmx/assets/htmx/src/ext/path-params.js +11 -0
  30. plain/htmx/assets/htmx/src/ext/preload.js +147 -0
  31. plain/htmx/assets/htmx/src/ext/rails-method.js +10 -0
  32. plain/htmx/assets/htmx/src/ext/remove-me.js +27 -0
  33. plain/htmx/assets/htmx/src/ext/response-targets.js +130 -0
  34. plain/htmx/assets/htmx/src/ext/restored.js +15 -0
  35. plain/htmx/assets/htmx/src/ext/sse.js +355 -0
  36. plain/htmx/assets/htmx/src/ext/ws.js +477 -0
  37. plain/htmx/assets/htmx/src/htmx.d.ts +450 -0
  38. plain/htmx/assets/htmx/src/htmx.js +3905 -0
  39. plain/htmx/assets/htmx/src/htmx.min.js +1 -0
  40. plain/htmx/assets/htmx/src/htmx.min.js.gz +0 -0
  41. plain/htmx/jinja.py +157 -0
  42. plain/htmx/templates/htmx/js.html +18 -0
  43. plain/htmx/views.py +74 -0
  44. plain_htmx-0.0.0.dist-info/LICENSE +28 -0
  45. plain_htmx-0.0.0.dist-info/METADATA +430 -0
  46. plain_htmx-0.0.0.dist-info/RECORD +47 -0
  47. plain_htmx-0.0.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,3905 @@
1
+ // UMD insanity
2
+ // This code sets up support for (in order) AMD, ES6 modules, and globals.
3
+ (function (root, factory) {
4
+ //@ts-ignore
5
+ if (typeof define === 'function' && define.amd) {
6
+ // AMD. Register as an anonymous module.
7
+ //@ts-ignore
8
+ define([], factory);
9
+ } else if (typeof module === 'object' && module.exports) {
10
+ // Node. Does not work with strict CommonJS, but
11
+ // only CommonJS-like environments that support module.exports,
12
+ // like Node.
13
+ module.exports = factory();
14
+ } else {
15
+ // Browser globals
16
+ root.htmx = root.htmx || factory();
17
+ }
18
+ }(typeof self !== 'undefined' ? self : this, function () {
19
+ return (function () {
20
+ 'use strict';
21
+
22
+ // Public API
23
+ //** @type {import("./htmx").HtmxApi} */
24
+ // TODO: list all methods in public API
25
+ var htmx = {
26
+ onLoad: onLoadHelper,
27
+ process: processNode,
28
+ on: addEventListenerImpl,
29
+ off: removeEventListenerImpl,
30
+ trigger : triggerEvent,
31
+ ajax : ajaxHelper,
32
+ find : find,
33
+ findAll : findAll,
34
+ closest : closest,
35
+ values : function(elt, type){
36
+ var inputValues = getInputValues(elt, type || "post");
37
+ return inputValues.values;
38
+ },
39
+ remove : removeElement,
40
+ addClass : addClassToElement,
41
+ removeClass : removeClassFromElement,
42
+ toggleClass : toggleClassOnElement,
43
+ takeClass : takeClassForElement,
44
+ defineExtension : defineExtension,
45
+ removeExtension : removeExtension,
46
+ logAll : logAll,
47
+ logNone : logNone,
48
+ logger : null,
49
+ config : {
50
+ historyEnabled:true,
51
+ historyCacheSize:10,
52
+ refreshOnHistoryMiss:false,
53
+ defaultSwapStyle:'innerHTML',
54
+ defaultSwapDelay:0,
55
+ defaultSettleDelay:20,
56
+ includeIndicatorStyles:true,
57
+ indicatorClass:'htmx-indicator',
58
+ requestClass:'htmx-request',
59
+ addedClass:'htmx-added',
60
+ settlingClass:'htmx-settling',
61
+ swappingClass:'htmx-swapping',
62
+ allowEval:true,
63
+ allowScriptTags:true,
64
+ inlineScriptNonce:'',
65
+ attributesToSettle:["class", "style", "width", "height"],
66
+ withCredentials:false,
67
+ timeout:0,
68
+ wsReconnectDelay: 'full-jitter',
69
+ wsBinaryType: 'blob',
70
+ disableSelector: "[hx-disable], [data-hx-disable]",
71
+ useTemplateFragments: false,
72
+ scrollBehavior: 'smooth',
73
+ defaultFocusScroll: false,
74
+ getCacheBusterParam: false,
75
+ globalViewTransitions: false,
76
+ methodsThatUseUrlParams: ["get"],
77
+ selfRequestsOnly: false,
78
+ ignoreTitle: false,
79
+ scrollIntoViewOnBoost: true,
80
+ triggerSpecsCache: null,
81
+ },
82
+ parseInterval:parseInterval,
83
+ _:internalEval,
84
+ createEventSource: function(url){
85
+ return new EventSource(url, {withCredentials:true})
86
+ },
87
+ createWebSocket: function(url){
88
+ var sock = new WebSocket(url, []);
89
+ sock.binaryType = htmx.config.wsBinaryType;
90
+ return sock;
91
+ },
92
+ version: "1.9.10"
93
+ };
94
+
95
+ /** @type {import("./htmx").HtmxInternalApi} */
96
+ var internalAPI = {
97
+ addTriggerHandler: addTriggerHandler,
98
+ bodyContains: bodyContains,
99
+ canAccessLocalStorage: canAccessLocalStorage,
100
+ findThisElement: findThisElement,
101
+ filterValues: filterValues,
102
+ hasAttribute: hasAttribute,
103
+ getAttributeValue: getAttributeValue,
104
+ getClosestAttributeValue: getClosestAttributeValue,
105
+ getClosestMatch: getClosestMatch,
106
+ getExpressionVars: getExpressionVars,
107
+ getHeaders: getHeaders,
108
+ getInputValues: getInputValues,
109
+ getInternalData: getInternalData,
110
+ getSwapSpecification: getSwapSpecification,
111
+ getTriggerSpecs: getTriggerSpecs,
112
+ getTarget: getTarget,
113
+ makeFragment: makeFragment,
114
+ mergeObjects: mergeObjects,
115
+ makeSettleInfo: makeSettleInfo,
116
+ oobSwap: oobSwap,
117
+ querySelectorExt: querySelectorExt,
118
+ selectAndSwap: selectAndSwap,
119
+ settleImmediately: settleImmediately,
120
+ shouldCancel: shouldCancel,
121
+ triggerEvent: triggerEvent,
122
+ triggerErrorEvent: triggerErrorEvent,
123
+ withExtensions: withExtensions,
124
+ }
125
+
126
+ var VERBS = ['get', 'post', 'put', 'delete', 'patch'];
127
+ var VERB_SELECTOR = VERBS.map(function(verb){
128
+ return "[hx-" + verb + "], [data-hx-" + verb + "]"
129
+ }).join(", ");
130
+
131
+ var HEAD_TAG_REGEX = makeTagRegEx('head'),
132
+ TITLE_TAG_REGEX = makeTagRegEx('title'),
133
+ SVG_TAGS_REGEX = makeTagRegEx('svg', true);
134
+
135
+ //====================================================================
136
+ // Utilities
137
+ //====================================================================
138
+
139
+ /**
140
+ * @param {string} tag
141
+ * @param {boolean} global
142
+ * @returns {RegExp}
143
+ */
144
+ function makeTagRegEx(tag, global = false) {
145
+ return new RegExp(`<${tag}(\\s[^>]*>|>)([\\s\\S]*?)<\\/${tag}>`,
146
+ global ? 'gim' : 'im');
147
+ }
148
+
149
+ function parseInterval(str) {
150
+ if (str == undefined) {
151
+ return undefined;
152
+ }
153
+
154
+ let interval = NaN;
155
+ if (str.slice(-2) == "ms") {
156
+ interval = parseFloat(str.slice(0, -2));
157
+ } else if (str.slice(-1) == "s") {
158
+ interval = parseFloat(str.slice(0, -1)) * 1000;
159
+ } else if (str.slice(-1) == "m") {
160
+ interval = parseFloat(str.slice(0, -1)) * 1000 * 60;
161
+ } else {
162
+ interval = parseFloat(str);
163
+ }
164
+ return isNaN(interval) ? undefined : interval;
165
+ }
166
+
167
+ /**
168
+ * @param {HTMLElement} elt
169
+ * @param {string} name
170
+ * @returns {(string | null)}
171
+ */
172
+ function getRawAttribute(elt, name) {
173
+ return elt.getAttribute && elt.getAttribute(name);
174
+ }
175
+
176
+ // resolve with both hx and data-hx prefixes
177
+ function hasAttribute(elt, qualifiedName) {
178
+ return elt.hasAttribute && (elt.hasAttribute(qualifiedName) ||
179
+ elt.hasAttribute("data-" + qualifiedName));
180
+ }
181
+
182
+ /**
183
+ *
184
+ * @param {HTMLElement} elt
185
+ * @param {string} qualifiedName
186
+ * @returns {(string | null)}
187
+ */
188
+ function getAttributeValue(elt, qualifiedName) {
189
+ return getRawAttribute(elt, qualifiedName) || getRawAttribute(elt, "data-" + qualifiedName);
190
+ }
191
+
192
+ /**
193
+ * @param {HTMLElement} elt
194
+ * @returns {HTMLElement | null}
195
+ */
196
+ function parentElt(elt) {
197
+ return elt.parentElement;
198
+ }
199
+
200
+ /**
201
+ * @returns {Document}
202
+ */
203
+ function getDocument() {
204
+ return document;
205
+ }
206
+
207
+ /**
208
+ * @param {HTMLElement} elt
209
+ * @param {(e:HTMLElement) => boolean} condition
210
+ * @returns {HTMLElement | null}
211
+ */
212
+ function getClosestMatch(elt, condition) {
213
+ while (elt && !condition(elt)) {
214
+ elt = parentElt(elt);
215
+ }
216
+
217
+ return elt ? elt : null;
218
+ }
219
+
220
+ function getAttributeValueWithDisinheritance(initialElement, ancestor, attributeName){
221
+ var attributeValue = getAttributeValue(ancestor, attributeName);
222
+ var disinherit = getAttributeValue(ancestor, "hx-disinherit");
223
+ if (initialElement !== ancestor && disinherit && (disinherit === "*" || disinherit.split(" ").indexOf(attributeName) >= 0)) {
224
+ return "unset";
225
+ } else {
226
+ return attributeValue
227
+ }
228
+ }
229
+
230
+ /**
231
+ * @param {HTMLElement} elt
232
+ * @param {string} attributeName
233
+ * @returns {string | null}
234
+ */
235
+ function getClosestAttributeValue(elt, attributeName) {
236
+ var closestAttr = null;
237
+ getClosestMatch(elt, function (e) {
238
+ return closestAttr = getAttributeValueWithDisinheritance(elt, e, attributeName);
239
+ });
240
+ if (closestAttr !== "unset") {
241
+ return closestAttr;
242
+ }
243
+ }
244
+
245
+ /**
246
+ * @param {HTMLElement} elt
247
+ * @param {string} selector
248
+ * @returns {boolean}
249
+ */
250
+ function matches(elt, selector) {
251
+ // @ts-ignore: non-standard properties for browser compatibility
252
+ // noinspection JSUnresolvedVariable
253
+ var matchesFunction = elt.matches || elt.matchesSelector || elt.msMatchesSelector || elt.mozMatchesSelector || elt.webkitMatchesSelector || elt.oMatchesSelector;
254
+ return matchesFunction && matchesFunction.call(elt, selector);
255
+ }
256
+
257
+ /**
258
+ * @param {string} str
259
+ * @returns {string}
260
+ */
261
+ function getStartTag(str) {
262
+ var tagMatcher = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i
263
+ var match = tagMatcher.exec( str );
264
+ if (match) {
265
+ return match[1].toLowerCase();
266
+ } else {
267
+ return "";
268
+ }
269
+ }
270
+
271
+ /**
272
+ *
273
+ * @param {string} resp
274
+ * @param {number} depth
275
+ * @returns {Element}
276
+ */
277
+ function parseHTML(resp, depth) {
278
+ var parser = new DOMParser();
279
+ var responseDoc = parser.parseFromString(resp, "text/html");
280
+
281
+ /** @type {Element} */
282
+ var responseNode = responseDoc.body;
283
+ while (depth > 0) {
284
+ depth--;
285
+ // @ts-ignore
286
+ responseNode = responseNode.firstChild;
287
+ }
288
+ if (responseNode == null) {
289
+ // @ts-ignore
290
+ responseNode = getDocument().createDocumentFragment();
291
+ }
292
+ return responseNode;
293
+ }
294
+
295
+ function aFullPageResponse(resp) {
296
+ return /<body/.test(resp)
297
+ }
298
+
299
+ /**
300
+ *
301
+ * @param {string} response
302
+ * @returns {Element}
303
+ */
304
+ function makeFragment(response) {
305
+ var partialResponse = !aFullPageResponse(response);
306
+ var startTag = getStartTag(response);
307
+ var content = response;
308
+ if (startTag === 'head') {
309
+ content = content.replace(HEAD_TAG_REGEX, '');
310
+ }
311
+ if (htmx.config.useTemplateFragments && partialResponse) {
312
+ var documentFragment = parseHTML("<body><template>" + content + "</template></body>", 0);
313
+ // @ts-ignore type mismatch between DocumentFragment and Element.
314
+ // TODO: Are these close enough for htmx to use interchangeably?
315
+ return documentFragment.querySelector('template').content;
316
+ }
317
+ switch (startTag) {
318
+ case "thead":
319
+ case "tbody":
320
+ case "tfoot":
321
+ case "colgroup":
322
+ case "caption":
323
+ return parseHTML("<table>" + content + "</table>", 1);
324
+ case "col":
325
+ return parseHTML("<table><colgroup>" + content + "</colgroup></table>", 2);
326
+ case "tr":
327
+ return parseHTML("<table><tbody>" + content + "</tbody></table>", 2);
328
+ case "td":
329
+ case "th":
330
+ return parseHTML("<table><tbody><tr>" + content + "</tr></tbody></table>", 3);
331
+ case "script":
332
+ case "style":
333
+ return parseHTML("<div>" + content + "</div>", 1);
334
+ default:
335
+ return parseHTML(content, 0);
336
+ }
337
+ }
338
+
339
+ /**
340
+ * @param {Function} func
341
+ */
342
+ function maybeCall(func){
343
+ if(func) {
344
+ func();
345
+ }
346
+ }
347
+
348
+ /**
349
+ * @param {any} o
350
+ * @param {string} type
351
+ * @returns
352
+ */
353
+ function isType(o, type) {
354
+ return Object.prototype.toString.call(o) === "[object " + type + "]";
355
+ }
356
+
357
+ /**
358
+ * @param {*} o
359
+ * @returns {o is Function}
360
+ */
361
+ function isFunction(o) {
362
+ return isType(o, "Function");
363
+ }
364
+
365
+ /**
366
+ * @param {*} o
367
+ * @returns {o is Object}
368
+ */
369
+ function isRawObject(o) {
370
+ return isType(o, "Object");
371
+ }
372
+
373
+ /**
374
+ * getInternalData retrieves "private" data stored by htmx within an element
375
+ * @param {HTMLElement} elt
376
+ * @returns {*}
377
+ */
378
+ function getInternalData(elt) {
379
+ var dataProp = 'htmx-internal-data';
380
+ var data = elt[dataProp];
381
+ if (!data) {
382
+ data = elt[dataProp] = {};
383
+ }
384
+ return data;
385
+ }
386
+
387
+ /**
388
+ * toArray converts an ArrayLike object into a real array.
389
+ * @param {ArrayLike} arr
390
+ * @returns {any[]}
391
+ */
392
+ function toArray(arr) {
393
+ var returnArr = [];
394
+ if (arr) {
395
+ for (var i = 0; i < arr.length; i++) {
396
+ returnArr.push(arr[i]);
397
+ }
398
+ }
399
+ return returnArr
400
+ }
401
+
402
+ function forEach(arr, func) {
403
+ if (arr) {
404
+ for (var i = 0; i < arr.length; i++) {
405
+ func(arr[i]);
406
+ }
407
+ }
408
+ }
409
+
410
+ function isScrolledIntoView(el) {
411
+ var rect = el.getBoundingClientRect();
412
+ var elemTop = rect.top;
413
+ var elemBottom = rect.bottom;
414
+ return elemTop < window.innerHeight && elemBottom >= 0;
415
+ }
416
+
417
+ function bodyContains(elt) {
418
+ // IE Fix
419
+ if (elt.getRootNode && elt.getRootNode() instanceof window.ShadowRoot) {
420
+ return getDocument().body.contains(elt.getRootNode().host);
421
+ } else {
422
+ return getDocument().body.contains(elt);
423
+ }
424
+ }
425
+
426
+ function splitOnWhitespace(trigger) {
427
+ return trigger.trim().split(/\s+/);
428
+ }
429
+
430
+ /**
431
+ * mergeObjects takes all of the keys from
432
+ * obj2 and duplicates them into obj1
433
+ * @param {Object} obj1
434
+ * @param {Object} obj2
435
+ * @returns {Object}
436
+ */
437
+ function mergeObjects(obj1, obj2) {
438
+ for (var key in obj2) {
439
+ if (obj2.hasOwnProperty(key)) {
440
+ obj1[key] = obj2[key];
441
+ }
442
+ }
443
+ return obj1;
444
+ }
445
+
446
+ function parseJSON(jString) {
447
+ try {
448
+ return JSON.parse(jString);
449
+ } catch(error) {
450
+ logError(error);
451
+ return null;
452
+ }
453
+ }
454
+
455
+ function canAccessLocalStorage() {
456
+ var test = 'htmx:localStorageTest';
457
+ try {
458
+ localStorage.setItem(test, test);
459
+ localStorage.removeItem(test);
460
+ return true;
461
+ } catch(e) {
462
+ return false;
463
+ }
464
+ }
465
+
466
+ function normalizePath(path) {
467
+ try {
468
+ var url = new URL(path);
469
+ if (url) {
470
+ path = url.pathname + url.search;
471
+ }
472
+ // remove trailing slash, unless index page
473
+ if (!(/^\/$/.test(path))) {
474
+ path = path.replace(/\/+$/, '');
475
+ }
476
+ return path;
477
+ } catch (e) {
478
+ // be kind to IE11, which doesn't support URL()
479
+ return path;
480
+ }
481
+ }
482
+
483
+ //==========================================================================================
484
+ // public API
485
+ //==========================================================================================
486
+
487
+ function internalEval(str){
488
+ return maybeEval(getDocument().body, function () {
489
+ return eval(str);
490
+ });
491
+ }
492
+
493
+ function onLoadHelper(callback) {
494
+ var value = htmx.on("htmx:load", function(evt) {
495
+ callback(evt.detail.elt);
496
+ });
497
+ return value;
498
+ }
499
+
500
+ function logAll(){
501
+ htmx.logger = function(elt, event, data) {
502
+ if(console) {
503
+ console.log(event, elt, data);
504
+ }
505
+ }
506
+ }
507
+
508
+ function logNone() {
509
+ htmx.logger = null
510
+ }
511
+
512
+ function find(eltOrSelector, selector) {
513
+ if (selector) {
514
+ return eltOrSelector.querySelector(selector);
515
+ } else {
516
+ return find(getDocument(), eltOrSelector);
517
+ }
518
+ }
519
+
520
+ function findAll(eltOrSelector, selector) {
521
+ if (selector) {
522
+ return eltOrSelector.querySelectorAll(selector);
523
+ } else {
524
+ return findAll(getDocument(), eltOrSelector);
525
+ }
526
+ }
527
+
528
+ function removeElement(elt, delay) {
529
+ elt = resolveTarget(elt);
530
+ if (delay) {
531
+ setTimeout(function(){
532
+ removeElement(elt);
533
+ elt = null;
534
+ }, delay);
535
+ } else {
536
+ elt.parentElement.removeChild(elt);
537
+ }
538
+ }
539
+
540
+ function addClassToElement(elt, clazz, delay) {
541
+ elt = resolveTarget(elt);
542
+ if (delay) {
543
+ setTimeout(function(){
544
+ addClassToElement(elt, clazz);
545
+ elt = null;
546
+ }, delay);
547
+ } else {
548
+ elt.classList && elt.classList.add(clazz);
549
+ }
550
+ }
551
+
552
+ function removeClassFromElement(elt, clazz, delay) {
553
+ elt = resolveTarget(elt);
554
+ if (delay) {
555
+ setTimeout(function(){
556
+ removeClassFromElement(elt, clazz);
557
+ elt = null;
558
+ }, delay);
559
+ } else {
560
+ if (elt.classList) {
561
+ elt.classList.remove(clazz);
562
+ // if there are no classes left, remove the class attribute
563
+ if (elt.classList.length === 0) {
564
+ elt.removeAttribute("class");
565
+ }
566
+ }
567
+ }
568
+ }
569
+
570
+ function toggleClassOnElement(elt, clazz) {
571
+ elt = resolveTarget(elt);
572
+ elt.classList.toggle(clazz);
573
+ }
574
+
575
+ function takeClassForElement(elt, clazz) {
576
+ elt = resolveTarget(elt);
577
+ forEach(elt.parentElement.children, function(child){
578
+ removeClassFromElement(child, clazz);
579
+ })
580
+ addClassToElement(elt, clazz);
581
+ }
582
+
583
+ function closest(elt, selector) {
584
+ elt = resolveTarget(elt);
585
+ if (elt.closest) {
586
+ return elt.closest(selector);
587
+ } else {
588
+ // TODO remove when IE goes away
589
+ do{
590
+ if (elt == null || matches(elt, selector)){
591
+ return elt;
592
+ }
593
+ }
594
+ while (elt = elt && parentElt(elt));
595
+ return null;
596
+ }
597
+ }
598
+
599
+ function startsWith(str, prefix) {
600
+ return str.substring(0, prefix.length) === prefix
601
+ }
602
+
603
+ function endsWith(str, suffix) {
604
+ return str.substring(str.length - suffix.length) === suffix
605
+ }
606
+
607
+ function normalizeSelector(selector) {
608
+ var trimmedSelector = selector.trim();
609
+ if (startsWith(trimmedSelector, "<") && endsWith(trimmedSelector, "/>")) {
610
+ return trimmedSelector.substring(1, trimmedSelector.length - 2);
611
+ } else {
612
+ return trimmedSelector;
613
+ }
614
+ }
615
+
616
+ function querySelectorAllExt(elt, selector) {
617
+ if (selector.indexOf("closest ") === 0) {
618
+ return [closest(elt, normalizeSelector(selector.substr(8)))];
619
+ } else if (selector.indexOf("find ") === 0) {
620
+ return [find(elt, normalizeSelector(selector.substr(5)))];
621
+ } else if (selector === "next") {
622
+ return [elt.nextElementSibling]
623
+ } else if (selector.indexOf("next ") === 0) {
624
+ return [scanForwardQuery(elt, normalizeSelector(selector.substr(5)))];
625
+ } else if (selector === "previous") {
626
+ return [elt.previousElementSibling]
627
+ } else if (selector.indexOf("previous ") === 0) {
628
+ return [scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)))];
629
+ } else if (selector === 'document') {
630
+ return [document];
631
+ } else if (selector === 'window') {
632
+ return [window];
633
+ } else if (selector === 'body') {
634
+ return [document.body];
635
+ } else {
636
+ return getDocument().querySelectorAll(normalizeSelector(selector));
637
+ }
638
+ }
639
+
640
+ var scanForwardQuery = function(start, match) {
641
+ var results = getDocument().querySelectorAll(match);
642
+ for (var i = 0; i < results.length; i++) {
643
+ var elt = results[i];
644
+ if (elt.compareDocumentPosition(start) === Node.DOCUMENT_POSITION_PRECEDING) {
645
+ return elt;
646
+ }
647
+ }
648
+ }
649
+
650
+ var scanBackwardsQuery = function(start, match) {
651
+ var results = getDocument().querySelectorAll(match);
652
+ for (var i = results.length - 1; i >= 0; i--) {
653
+ var elt = results[i];
654
+ if (elt.compareDocumentPosition(start) === Node.DOCUMENT_POSITION_FOLLOWING) {
655
+ return elt;
656
+ }
657
+ }
658
+ }
659
+
660
+ function querySelectorExt(eltOrSelector, selector) {
661
+ if (selector) {
662
+ return querySelectorAllExt(eltOrSelector, selector)[0];
663
+ } else {
664
+ return querySelectorAllExt(getDocument().body, eltOrSelector)[0];
665
+ }
666
+ }
667
+
668
+ function resolveTarget(arg2) {
669
+ if (isType(arg2, 'String')) {
670
+ return find(arg2);
671
+ } else {
672
+ return arg2;
673
+ }
674
+ }
675
+
676
+ function processEventArgs(arg1, arg2, arg3) {
677
+ if (isFunction(arg2)) {
678
+ return {
679
+ target: getDocument().body,
680
+ event: arg1,
681
+ listener: arg2
682
+ }
683
+ } else {
684
+ return {
685
+ target: resolveTarget(arg1),
686
+ event: arg2,
687
+ listener: arg3
688
+ }
689
+ }
690
+
691
+ }
692
+
693
+ function addEventListenerImpl(arg1, arg2, arg3) {
694
+ ready(function(){
695
+ var eventArgs = processEventArgs(arg1, arg2, arg3);
696
+ eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener);
697
+ })
698
+ var b = isFunction(arg2);
699
+ return b ? arg2 : arg3;
700
+ }
701
+
702
+ function removeEventListenerImpl(arg1, arg2, arg3) {
703
+ ready(function(){
704
+ var eventArgs = processEventArgs(arg1, arg2, arg3);
705
+ eventArgs.target.removeEventListener(eventArgs.event, eventArgs.listener);
706
+ })
707
+ return isFunction(arg2) ? arg2 : arg3;
708
+ }
709
+
710
+ //====================================================================
711
+ // Node processing
712
+ //====================================================================
713
+
714
+ var DUMMY_ELT = getDocument().createElement("output"); // dummy element for bad selectors
715
+ function findAttributeTargets(elt, attrName) {
716
+ var attrTarget = getClosestAttributeValue(elt, attrName);
717
+ if (attrTarget) {
718
+ if (attrTarget === "this") {
719
+ return [findThisElement(elt, attrName)];
720
+ } else {
721
+ var result = querySelectorAllExt(elt, attrTarget);
722
+ if (result.length === 0) {
723
+ logError('The selector "' + attrTarget + '" on ' + attrName + " returned no matches!");
724
+ return [DUMMY_ELT]
725
+ } else {
726
+ return result;
727
+ }
728
+ }
729
+ }
730
+ }
731
+
732
+ function findThisElement(elt, attribute){
733
+ return getClosestMatch(elt, function (elt) {
734
+ return getAttributeValue(elt, attribute) != null;
735
+ })
736
+ }
737
+
738
+ function getTarget(elt) {
739
+ var targetStr = getClosestAttributeValue(elt, "hx-target");
740
+ if (targetStr) {
741
+ if (targetStr === "this") {
742
+ return findThisElement(elt,'hx-target');
743
+ } else {
744
+ return querySelectorExt(elt, targetStr)
745
+ }
746
+ } else {
747
+ var data = getInternalData(elt);
748
+ if (data.boosted) {
749
+ return getDocument().body;
750
+ } else {
751
+ return elt;
752
+ }
753
+ }
754
+ }
755
+
756
+ function shouldSettleAttribute(name) {
757
+ var attributesToSettle = htmx.config.attributesToSettle;
758
+ for (var i = 0; i < attributesToSettle.length; i++) {
759
+ if (name === attributesToSettle[i]) {
760
+ return true;
761
+ }
762
+ }
763
+ return false;
764
+ }
765
+
766
+ function cloneAttributes(mergeTo, mergeFrom) {
767
+ forEach(mergeTo.attributes, function (attr) {
768
+ if (!mergeFrom.hasAttribute(attr.name) && shouldSettleAttribute(attr.name)) {
769
+ mergeTo.removeAttribute(attr.name)
770
+ }
771
+ });
772
+ forEach(mergeFrom.attributes, function (attr) {
773
+ if (shouldSettleAttribute(attr.name)) {
774
+ mergeTo.setAttribute(attr.name, attr.value);
775
+ }
776
+ });
777
+ }
778
+
779
+ function isInlineSwap(swapStyle, target) {
780
+ var extensions = getExtensions(target);
781
+ for (var i = 0; i < extensions.length; i++) {
782
+ var extension = extensions[i];
783
+ try {
784
+ if (extension.isInlineSwap(swapStyle)) {
785
+ return true;
786
+ }
787
+ } catch(e) {
788
+ logError(e);
789
+ }
790
+ }
791
+ return swapStyle === "outerHTML";
792
+ }
793
+
794
+ /**
795
+ *
796
+ * @param {string} oobValue
797
+ * @param {HTMLElement} oobElement
798
+ * @param {*} settleInfo
799
+ * @returns
800
+ */
801
+ function oobSwap(oobValue, oobElement, settleInfo) {
802
+ var selector = "#" + getRawAttribute(oobElement, "id");
803
+ var swapStyle = "outerHTML";
804
+ if (oobValue === "true") {
805
+ // do nothing
806
+ } else if (oobValue.indexOf(":") > 0) {
807
+ swapStyle = oobValue.substr(0, oobValue.indexOf(":"));
808
+ selector = oobValue.substr(oobValue.indexOf(":") + 1, oobValue.length);
809
+ } else {
810
+ swapStyle = oobValue;
811
+ }
812
+
813
+ var targets = getDocument().querySelectorAll(selector);
814
+ if (targets) {
815
+ forEach(
816
+ targets,
817
+ function (target) {
818
+ var fragment;
819
+ var oobElementClone = oobElement.cloneNode(true);
820
+ fragment = getDocument().createDocumentFragment();
821
+ fragment.appendChild(oobElementClone);
822
+ if (!isInlineSwap(swapStyle, target)) {
823
+ fragment = oobElementClone; // if this is not an inline swap, we use the content of the node, not the node itself
824
+ }
825
+
826
+ var beforeSwapDetails = {shouldSwap: true, target: target, fragment:fragment };
827
+ if (!triggerEvent(target, 'htmx:oobBeforeSwap', beforeSwapDetails)) return;
828
+
829
+ target = beforeSwapDetails.target; // allow re-targeting
830
+ if (beforeSwapDetails['shouldSwap']){
831
+ swap(swapStyle, target, target, fragment, settleInfo);
832
+ }
833
+ forEach(settleInfo.elts, function (elt) {
834
+ triggerEvent(elt, 'htmx:oobAfterSwap', beforeSwapDetails);
835
+ });
836
+ }
837
+ );
838
+ oobElement.parentNode.removeChild(oobElement);
839
+ } else {
840
+ oobElement.parentNode.removeChild(oobElement);
841
+ triggerErrorEvent(getDocument().body, "htmx:oobErrorNoTarget", {content: oobElement});
842
+ }
843
+ return oobValue;
844
+ }
845
+
846
+ function handleOutOfBandSwaps(elt, fragment, settleInfo) {
847
+ var oobSelects = getClosestAttributeValue(elt, "hx-select-oob");
848
+ if (oobSelects) {
849
+ var oobSelectValues = oobSelects.split(",");
850
+ for (var i = 0; i < oobSelectValues.length; i++) {
851
+ var oobSelectValue = oobSelectValues[i].split(":", 2);
852
+ var id = oobSelectValue[0].trim();
853
+ if (id.indexOf("#") === 0) {
854
+ id = id.substring(1);
855
+ }
856
+ var oobValue = oobSelectValue[1] || "true";
857
+ var oobElement = fragment.querySelector("#" + id);
858
+ if (oobElement) {
859
+ oobSwap(oobValue, oobElement, settleInfo);
860
+ }
861
+ }
862
+ }
863
+ forEach(findAll(fragment, '[hx-swap-oob], [data-hx-swap-oob]'), function (oobElement) {
864
+ var oobValue = getAttributeValue(oobElement, "hx-swap-oob");
865
+ if (oobValue != null) {
866
+ oobSwap(oobValue, oobElement, settleInfo);
867
+ }
868
+ });
869
+ }
870
+
871
+ function handlePreservedElements(fragment) {
872
+ forEach(findAll(fragment, '[hx-preserve], [data-hx-preserve]'), function (preservedElt) {
873
+ var id = getAttributeValue(preservedElt, "id");
874
+ var oldElt = getDocument().getElementById(id);
875
+ if (oldElt != null) {
876
+ preservedElt.parentNode.replaceChild(oldElt, preservedElt);
877
+ }
878
+ });
879
+ }
880
+
881
+ function handleAttributes(parentNode, fragment, settleInfo) {
882
+ forEach(fragment.querySelectorAll("[id]"), function (newNode) {
883
+ var id = getRawAttribute(newNode, "id")
884
+ if (id && id.length > 0) {
885
+ var normalizedId = id.replace("'", "\\'");
886
+ var normalizedTag = newNode.tagName.replace(':', '\\:');
887
+ var oldNode = parentNode.querySelector(normalizedTag + "[id='" + normalizedId + "']");
888
+ if (oldNode && oldNode !== parentNode) {
889
+ var newAttributes = newNode.cloneNode();
890
+ cloneAttributes(newNode, oldNode);
891
+ settleInfo.tasks.push(function () {
892
+ cloneAttributes(newNode, newAttributes);
893
+ });
894
+ }
895
+ }
896
+ });
897
+ }
898
+
899
+ function makeAjaxLoadTask(child) {
900
+ return function () {
901
+ removeClassFromElement(child, htmx.config.addedClass);
902
+ processNode(child);
903
+ processScripts(child);
904
+ processFocus(child)
905
+ triggerEvent(child, 'htmx:load');
906
+ };
907
+ }
908
+
909
+ function processFocus(child) {
910
+ var autofocus = "[autofocus]";
911
+ var autoFocusedElt = matches(child, autofocus) ? child : child.querySelector(autofocus)
912
+ if (autoFocusedElt != null) {
913
+ autoFocusedElt.focus();
914
+ }
915
+ }
916
+
917
+ function insertNodesBefore(parentNode, insertBefore, fragment, settleInfo) {
918
+ handleAttributes(parentNode, fragment, settleInfo);
919
+ while(fragment.childNodes.length > 0){
920
+ var child = fragment.firstChild;
921
+ addClassToElement(child, htmx.config.addedClass);
922
+ parentNode.insertBefore(child, insertBefore);
923
+ if (child.nodeType !== Node.TEXT_NODE && child.nodeType !== Node.COMMENT_NODE) {
924
+ settleInfo.tasks.push(makeAjaxLoadTask(child));
925
+ }
926
+ }
927
+ }
928
+
929
+ // based on https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0,
930
+ // derived from Java's string hashcode implementation
931
+ function stringHash(string, hash) {
932
+ var char = 0;
933
+ while (char < string.length){
934
+ hash = (hash << 5) - hash + string.charCodeAt(char++) | 0; // bitwise or ensures we have a 32-bit int
935
+ }
936
+ return hash;
937
+ }
938
+
939
+ function attributeHash(elt) {
940
+ var hash = 0;
941
+ // IE fix
942
+ if (elt.attributes) {
943
+ for (var i = 0; i < elt.attributes.length; i++) {
944
+ var attribute = elt.attributes[i];
945
+ if(attribute.value){ // only include attributes w/ actual values (empty is same as non-existent)
946
+ hash = stringHash(attribute.name, hash);
947
+ hash = stringHash(attribute.value, hash);
948
+ }
949
+ }
950
+ }
951
+ return hash;
952
+ }
953
+
954
+ function deInitOnHandlers(elt) {
955
+ var internalData = getInternalData(elt);
956
+ if (internalData.onHandlers) {
957
+ for (var i = 0; i < internalData.onHandlers.length; i++) {
958
+ const handlerInfo = internalData.onHandlers[i];
959
+ elt.removeEventListener(handlerInfo.event, handlerInfo.listener);
960
+ }
961
+ delete internalData.onHandlers
962
+ }
963
+ }
964
+
965
+ function deInitNode(element) {
966
+ var internalData = getInternalData(element);
967
+ if (internalData.timeout) {
968
+ clearTimeout(internalData.timeout);
969
+ }
970
+ if (internalData.webSocket) {
971
+ internalData.webSocket.close();
972
+ }
973
+ if (internalData.sseEventSource) {
974
+ internalData.sseEventSource.close();
975
+ }
976
+ if (internalData.listenerInfos) {
977
+ forEach(internalData.listenerInfos, function (info) {
978
+ if (info.on) {
979
+ info.on.removeEventListener(info.trigger, info.listener);
980
+ }
981
+ });
982
+ }
983
+ deInitOnHandlers(element);
984
+ forEach(Object.keys(internalData), function(key) { delete internalData[key] });
985
+ }
986
+
987
+ function cleanUpElement(element) {
988
+ triggerEvent(element, "htmx:beforeCleanupElement")
989
+ deInitNode(element);
990
+ if (element.children) { // IE
991
+ forEach(element.children, function(child) { cleanUpElement(child) });
992
+ }
993
+ }
994
+
995
+ function swapOuterHTML(target, fragment, settleInfo) {
996
+ if (target.tagName === "BODY") {
997
+ return swapInnerHTML(target, fragment, settleInfo);
998
+ } else {
999
+ // @type {HTMLElement}
1000
+ var newElt
1001
+ var eltBeforeNewContent = target.previousSibling;
1002
+ insertNodesBefore(parentElt(target), target, fragment, settleInfo);
1003
+ if (eltBeforeNewContent == null) {
1004
+ newElt = parentElt(target).firstChild;
1005
+ } else {
1006
+ newElt = eltBeforeNewContent.nextSibling;
1007
+ }
1008
+ settleInfo.elts = settleInfo.elts.filter(function(e) { return e != target });
1009
+ while(newElt && newElt !== target) {
1010
+ if (newElt.nodeType === Node.ELEMENT_NODE) {
1011
+ settleInfo.elts.push(newElt);
1012
+ }
1013
+ newElt = newElt.nextElementSibling;
1014
+ }
1015
+ cleanUpElement(target);
1016
+ parentElt(target).removeChild(target);
1017
+ }
1018
+ }
1019
+
1020
+ function swapAfterBegin(target, fragment, settleInfo) {
1021
+ return insertNodesBefore(target, target.firstChild, fragment, settleInfo);
1022
+ }
1023
+
1024
+ function swapBeforeBegin(target, fragment, settleInfo) {
1025
+ return insertNodesBefore(parentElt(target), target, fragment, settleInfo);
1026
+ }
1027
+
1028
+ function swapBeforeEnd(target, fragment, settleInfo) {
1029
+ return insertNodesBefore(target, null, fragment, settleInfo);
1030
+ }
1031
+
1032
+ function swapAfterEnd(target, fragment, settleInfo) {
1033
+ return insertNodesBefore(parentElt(target), target.nextSibling, fragment, settleInfo);
1034
+ }
1035
+ function swapDelete(target, fragment, settleInfo) {
1036
+ cleanUpElement(target);
1037
+ return parentElt(target).removeChild(target);
1038
+ }
1039
+
1040
+ function swapInnerHTML(target, fragment, settleInfo) {
1041
+ var firstChild = target.firstChild;
1042
+ insertNodesBefore(target, firstChild, fragment, settleInfo);
1043
+ if (firstChild) {
1044
+ while (firstChild.nextSibling) {
1045
+ cleanUpElement(firstChild.nextSibling)
1046
+ target.removeChild(firstChild.nextSibling);
1047
+ }
1048
+ cleanUpElement(firstChild)
1049
+ target.removeChild(firstChild);
1050
+ }
1051
+ }
1052
+
1053
+ function maybeSelectFromResponse(elt, fragment, selectOverride) {
1054
+ var selector = selectOverride || getClosestAttributeValue(elt, "hx-select");
1055
+ if (selector) {
1056
+ var newFragment = getDocument().createDocumentFragment();
1057
+ forEach(fragment.querySelectorAll(selector), function (node) {
1058
+ newFragment.appendChild(node);
1059
+ });
1060
+ fragment = newFragment;
1061
+ }
1062
+ return fragment;
1063
+ }
1064
+
1065
+ function swap(swapStyle, elt, target, fragment, settleInfo) {
1066
+ switch (swapStyle) {
1067
+ case "none":
1068
+ return;
1069
+ case "outerHTML":
1070
+ swapOuterHTML(target, fragment, settleInfo);
1071
+ return;
1072
+ case "afterbegin":
1073
+ swapAfterBegin(target, fragment, settleInfo);
1074
+ return;
1075
+ case "beforebegin":
1076
+ swapBeforeBegin(target, fragment, settleInfo);
1077
+ return;
1078
+ case "beforeend":
1079
+ swapBeforeEnd(target, fragment, settleInfo);
1080
+ return;
1081
+ case "afterend":
1082
+ swapAfterEnd(target, fragment, settleInfo);
1083
+ return;
1084
+ case "delete":
1085
+ swapDelete(target, fragment, settleInfo);
1086
+ return;
1087
+ default:
1088
+ var extensions = getExtensions(elt);
1089
+ for (var i = 0; i < extensions.length; i++) {
1090
+ var ext = extensions[i];
1091
+ try {
1092
+ var newElements = ext.handleSwap(swapStyle, target, fragment, settleInfo);
1093
+ if (newElements) {
1094
+ if (typeof newElements.length !== 'undefined') {
1095
+ // if handleSwap returns an array (like) of elements, we handle them
1096
+ for (var j = 0; j < newElements.length; j++) {
1097
+ var child = newElements[j];
1098
+ if (child.nodeType !== Node.TEXT_NODE && child.nodeType !== Node.COMMENT_NODE) {
1099
+ settleInfo.tasks.push(makeAjaxLoadTask(child));
1100
+ }
1101
+ }
1102
+ }
1103
+ return;
1104
+ }
1105
+ } catch (e) {
1106
+ logError(e);
1107
+ }
1108
+ }
1109
+ if (swapStyle === "innerHTML") {
1110
+ swapInnerHTML(target, fragment, settleInfo);
1111
+ } else {
1112
+ swap(htmx.config.defaultSwapStyle, elt, target, fragment, settleInfo);
1113
+ }
1114
+ }
1115
+ }
1116
+
1117
+ function findTitle(content) {
1118
+ if (content.indexOf('<title') > -1) {
1119
+ var contentWithSvgsRemoved = content.replace(SVG_TAGS_REGEX, '');
1120
+ var result = contentWithSvgsRemoved.match(TITLE_TAG_REGEX);
1121
+ if (result) {
1122
+ return result[2];
1123
+ }
1124
+ }
1125
+ }
1126
+
1127
+ function selectAndSwap(swapStyle, target, elt, responseText, settleInfo, selectOverride) {
1128
+ settleInfo.title = findTitle(responseText);
1129
+ var fragment = makeFragment(responseText);
1130
+ if (fragment) {
1131
+ handleOutOfBandSwaps(elt, fragment, settleInfo);
1132
+ fragment = maybeSelectFromResponse(elt, fragment, selectOverride);
1133
+ handlePreservedElements(fragment);
1134
+ return swap(swapStyle, elt, target, fragment, settleInfo);
1135
+ }
1136
+ }
1137
+
1138
+ function handleTrigger(xhr, header, elt) {
1139
+ var triggerBody = xhr.getResponseHeader(header);
1140
+ if (triggerBody.indexOf("{") === 0) {
1141
+ var triggers = parseJSON(triggerBody);
1142
+ for (var eventName in triggers) {
1143
+ if (triggers.hasOwnProperty(eventName)) {
1144
+ var detail = triggers[eventName];
1145
+ if (!isRawObject(detail)) {
1146
+ detail = {"value": detail}
1147
+ }
1148
+ triggerEvent(elt, eventName, detail);
1149
+ }
1150
+ }
1151
+ } else {
1152
+ var eventNames = triggerBody.split(",")
1153
+ for (var i = 0; i < eventNames.length; i++) {
1154
+ triggerEvent(elt, eventNames[i].trim(), []);
1155
+ }
1156
+ }
1157
+ }
1158
+
1159
+ var WHITESPACE = /\s/;
1160
+ var WHITESPACE_OR_COMMA = /[\s,]/;
1161
+ var SYMBOL_START = /[_$a-zA-Z]/;
1162
+ var SYMBOL_CONT = /[_$a-zA-Z0-9]/;
1163
+ var STRINGISH_START = ['"', "'", "/"];
1164
+ var NOT_WHITESPACE = /[^\s]/;
1165
+ var COMBINED_SELECTOR_START = /[{(]/;
1166
+ var COMBINED_SELECTOR_END = /[})]/;
1167
+ function tokenizeString(str) {
1168
+ var tokens = [];
1169
+ var position = 0;
1170
+ while (position < str.length) {
1171
+ if(SYMBOL_START.exec(str.charAt(position))) {
1172
+ var startPosition = position;
1173
+ while (SYMBOL_CONT.exec(str.charAt(position + 1))) {
1174
+ position++;
1175
+ }
1176
+ tokens.push(str.substr(startPosition, position - startPosition + 1));
1177
+ } else if (STRINGISH_START.indexOf(str.charAt(position)) !== -1) {
1178
+ var startChar = str.charAt(position);
1179
+ var startPosition = position;
1180
+ position++;
1181
+ while (position < str.length && str.charAt(position) !== startChar ) {
1182
+ if (str.charAt(position) === "\\") {
1183
+ position++;
1184
+ }
1185
+ position++;
1186
+ }
1187
+ tokens.push(str.substr(startPosition, position - startPosition + 1));
1188
+ } else {
1189
+ var symbol = str.charAt(position);
1190
+ tokens.push(symbol);
1191
+ }
1192
+ position++;
1193
+ }
1194
+ return tokens;
1195
+ }
1196
+
1197
+ function isPossibleRelativeReference(token, last, paramName) {
1198
+ return SYMBOL_START.exec(token.charAt(0)) &&
1199
+ token !== "true" &&
1200
+ token !== "false" &&
1201
+ token !== "this" &&
1202
+ token !== paramName &&
1203
+ last !== ".";
1204
+ }
1205
+
1206
+ function maybeGenerateConditional(elt, tokens, paramName) {
1207
+ if (tokens[0] === '[') {
1208
+ tokens.shift();
1209
+ var bracketCount = 1;
1210
+ var conditionalSource = " return (function(" + paramName + "){ return (";
1211
+ var last = null;
1212
+ while (tokens.length > 0) {
1213
+ var token = tokens[0];
1214
+ if (token === "]") {
1215
+ bracketCount--;
1216
+ if (bracketCount === 0) {
1217
+ if (last === null) {
1218
+ conditionalSource = conditionalSource + "true";
1219
+ }
1220
+ tokens.shift();
1221
+ conditionalSource += ")})";
1222
+ try {
1223
+ var conditionFunction = maybeEval(elt,function () {
1224
+ return Function(conditionalSource)();
1225
+ },
1226
+ function(){return true})
1227
+ conditionFunction.source = conditionalSource;
1228
+ return conditionFunction;
1229
+ } catch (e) {
1230
+ triggerErrorEvent(getDocument().body, "htmx:syntax:error", {error:e, source:conditionalSource})
1231
+ return null;
1232
+ }
1233
+ }
1234
+ } else if (token === "[") {
1235
+ bracketCount++;
1236
+ }
1237
+ if (isPossibleRelativeReference(token, last, paramName)) {
1238
+ conditionalSource += "((" + paramName + "." + token + ") ? (" + paramName + "." + token + ") : (window." + token + "))";
1239
+ } else {
1240
+ conditionalSource = conditionalSource + token;
1241
+ }
1242
+ last = tokens.shift();
1243
+ }
1244
+ }
1245
+ }
1246
+
1247
+ function consumeUntil(tokens, match) {
1248
+ var result = "";
1249
+ while (tokens.length > 0 && !match.test(tokens[0])) {
1250
+ result += tokens.shift();
1251
+ }
1252
+ return result;
1253
+ }
1254
+
1255
+ function consumeCSSSelector(tokens) {
1256
+ var result;
1257
+ if (tokens.length > 0 && COMBINED_SELECTOR_START.test(tokens[0])) {
1258
+ tokens.shift();
1259
+ result = consumeUntil(tokens, COMBINED_SELECTOR_END).trim();
1260
+ tokens.shift();
1261
+ } else {
1262
+ result = consumeUntil(tokens, WHITESPACE_OR_COMMA);
1263
+ }
1264
+ return result;
1265
+ }
1266
+
1267
+ var INPUT_SELECTOR = 'input, textarea, select';
1268
+
1269
+ /**
1270
+ * @param {HTMLElement} elt
1271
+ * @param {string} explicitTrigger
1272
+ * @param {cache} cache for trigger specs
1273
+ * @returns {import("./htmx").HtmxTriggerSpecification[]}
1274
+ */
1275
+ function parseAndCacheTrigger(elt, explicitTrigger, cache) {
1276
+ var triggerSpecs = [];
1277
+ var tokens = tokenizeString(explicitTrigger);
1278
+ do {
1279
+ consumeUntil(tokens, NOT_WHITESPACE);
1280
+ var initialLength = tokens.length;
1281
+ var trigger = consumeUntil(tokens, /[,\[\s]/);
1282
+ if (trigger !== "") {
1283
+ if (trigger === "every") {
1284
+ var every = {trigger: 'every'};
1285
+ consumeUntil(tokens, NOT_WHITESPACE);
1286
+ every.pollInterval = parseInterval(consumeUntil(tokens, /[,\[\s]/));
1287
+ consumeUntil(tokens, NOT_WHITESPACE);
1288
+ var eventFilter = maybeGenerateConditional(elt, tokens, "event");
1289
+ if (eventFilter) {
1290
+ every.eventFilter = eventFilter;
1291
+ }
1292
+ triggerSpecs.push(every);
1293
+ } else if (trigger.indexOf("sse:") === 0) {
1294
+ triggerSpecs.push({trigger: 'sse', sseEvent: trigger.substr(4)});
1295
+ } else {
1296
+ var triggerSpec = {trigger: trigger};
1297
+ var eventFilter = maybeGenerateConditional(elt, tokens, "event");
1298
+ if (eventFilter) {
1299
+ triggerSpec.eventFilter = eventFilter;
1300
+ }
1301
+ while (tokens.length > 0 && tokens[0] !== ",") {
1302
+ consumeUntil(tokens, NOT_WHITESPACE)
1303
+ var token = tokens.shift();
1304
+ if (token === "changed") {
1305
+ triggerSpec.changed = true;
1306
+ } else if (token === "once") {
1307
+ triggerSpec.once = true;
1308
+ } else if (token === "consume") {
1309
+ triggerSpec.consume = true;
1310
+ } else if (token === "delay" && tokens[0] === ":") {
1311
+ tokens.shift();
1312
+ triggerSpec.delay = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA));
1313
+ } else if (token === "from" && tokens[0] === ":") {
1314
+ tokens.shift();
1315
+ if (COMBINED_SELECTOR_START.test(tokens[0])) {
1316
+ var from_arg = consumeCSSSelector(tokens);
1317
+ } else {
1318
+ var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA);
1319
+ if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") {
1320
+ tokens.shift();
1321
+ var selector = consumeCSSSelector(tokens);
1322
+ // `next` and `previous` allow a selector-less syntax
1323
+ if (selector.length > 0) {
1324
+ from_arg += " " + selector;
1325
+ }
1326
+ }
1327
+ }
1328
+ triggerSpec.from = from_arg;
1329
+ } else if (token === "target" && tokens[0] === ":") {
1330
+ tokens.shift();
1331
+ triggerSpec.target = consumeCSSSelector(tokens);
1332
+ } else if (token === "throttle" && tokens[0] === ":") {
1333
+ tokens.shift();
1334
+ triggerSpec.throttle = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA));
1335
+ } else if (token === "queue" && tokens[0] === ":") {
1336
+ tokens.shift();
1337
+ triggerSpec.queue = consumeUntil(tokens, WHITESPACE_OR_COMMA);
1338
+ } else if (token === "root" && tokens[0] === ":") {
1339
+ tokens.shift();
1340
+ triggerSpec[token] = consumeCSSSelector(tokens);
1341
+ } else if (token === "threshold" && tokens[0] === ":") {
1342
+ tokens.shift();
1343
+ triggerSpec[token] = consumeUntil(tokens, WHITESPACE_OR_COMMA);
1344
+ } else {
1345
+ triggerErrorEvent(elt, "htmx:syntax:error", {token:tokens.shift()});
1346
+ }
1347
+ }
1348
+ triggerSpecs.push(triggerSpec);
1349
+ }
1350
+ }
1351
+ if (tokens.length === initialLength) {
1352
+ triggerErrorEvent(elt, "htmx:syntax:error", {token:tokens.shift()});
1353
+ }
1354
+ consumeUntil(tokens, NOT_WHITESPACE);
1355
+ } while (tokens[0] === "," && tokens.shift())
1356
+ if (cache) {
1357
+ cache[explicitTrigger] = triggerSpecs
1358
+ }
1359
+ return triggerSpecs
1360
+ }
1361
+
1362
+ /**
1363
+ * @param {HTMLElement} elt
1364
+ * @returns {import("./htmx").HtmxTriggerSpecification[]}
1365
+ */
1366
+ function getTriggerSpecs(elt) {
1367
+ var explicitTrigger = getAttributeValue(elt, 'hx-trigger');
1368
+ var triggerSpecs = [];
1369
+ if (explicitTrigger) {
1370
+ var cache = htmx.config.triggerSpecsCache
1371
+ triggerSpecs = (cache && cache[explicitTrigger]) || parseAndCacheTrigger(elt, explicitTrigger, cache)
1372
+ }
1373
+
1374
+ if (triggerSpecs.length > 0) {
1375
+ return triggerSpecs;
1376
+ } else if (matches(elt, 'form')) {
1377
+ return [{trigger: 'submit'}];
1378
+ } else if (matches(elt, 'input[type="button"], input[type="submit"]')){
1379
+ return [{trigger: 'click'}];
1380
+ } else if (matches(elt, INPUT_SELECTOR)) {
1381
+ return [{trigger: 'change'}];
1382
+ } else {
1383
+ return [{trigger: 'click'}];
1384
+ }
1385
+ }
1386
+
1387
+ function cancelPolling(elt) {
1388
+ getInternalData(elt).cancelled = true;
1389
+ }
1390
+
1391
+ function processPolling(elt, handler, spec) {
1392
+ var nodeData = getInternalData(elt);
1393
+ nodeData.timeout = setTimeout(function () {
1394
+ if (bodyContains(elt) && nodeData.cancelled !== true) {
1395
+ if (!maybeFilterEvent(spec, elt, makeEvent('hx:poll:trigger', {
1396
+ triggerSpec: spec,
1397
+ target: elt
1398
+ }))) {
1399
+ handler(elt);
1400
+ }
1401
+ processPolling(elt, handler, spec);
1402
+ }
1403
+ }, spec.pollInterval);
1404
+ }
1405
+
1406
+ function isLocalLink(elt) {
1407
+ return location.hostname === elt.hostname &&
1408
+ getRawAttribute(elt,'href') &&
1409
+ getRawAttribute(elt,'href').indexOf("#") !== 0;
1410
+ }
1411
+
1412
+ function boostElement(elt, nodeData, triggerSpecs) {
1413
+ if ((elt.tagName === "A" && isLocalLink(elt) && (elt.target === "" || elt.target === "_self")) || elt.tagName === "FORM") {
1414
+ nodeData.boosted = true;
1415
+ var verb, path;
1416
+ if (elt.tagName === "A") {
1417
+ verb = "get";
1418
+ path = getRawAttribute(elt, 'href')
1419
+ } else {
1420
+ var rawAttribute = getRawAttribute(elt, "method");
1421
+ verb = rawAttribute ? rawAttribute.toLowerCase() : "get";
1422
+ if (verb === "get") {
1423
+ }
1424
+ path = getRawAttribute(elt, 'action');
1425
+ }
1426
+ triggerSpecs.forEach(function(triggerSpec) {
1427
+ addEventListener(elt, function(elt, evt) {
1428
+ if (closest(elt, htmx.config.disableSelector)) {
1429
+ cleanUpElement(elt)
1430
+ return
1431
+ }
1432
+ issueAjaxRequest(verb, path, elt, evt)
1433
+ }, nodeData, triggerSpec, true);
1434
+ });
1435
+ }
1436
+ }
1437
+
1438
+ /**
1439
+ *
1440
+ * @param {Event} evt
1441
+ * @param {HTMLElement} elt
1442
+ * @returns
1443
+ */
1444
+ function shouldCancel(evt, elt) {
1445
+ if (evt.type === "submit" || evt.type === "click") {
1446
+ if (elt.tagName === "FORM") {
1447
+ return true;
1448
+ }
1449
+ if (matches(elt, 'input[type="submit"], button') && closest(elt, 'form') !== null) {
1450
+ return true;
1451
+ }
1452
+ if (elt.tagName === "A" && elt.href &&
1453
+ (elt.getAttribute('href') === '#' || elt.getAttribute('href').indexOf("#") !== 0)) {
1454
+ return true;
1455
+ }
1456
+ }
1457
+ return false;
1458
+ }
1459
+
1460
+ function ignoreBoostedAnchorCtrlClick(elt, evt) {
1461
+ return getInternalData(elt).boosted && elt.tagName === "A" && evt.type === "click" && (evt.ctrlKey || evt.metaKey);
1462
+ }
1463
+
1464
+ function maybeFilterEvent(triggerSpec, elt, evt) {
1465
+ var eventFilter = triggerSpec.eventFilter;
1466
+ if(eventFilter){
1467
+ try {
1468
+ return eventFilter.call(elt, evt) !== true;
1469
+ } catch(e) {
1470
+ triggerErrorEvent(getDocument().body, "htmx:eventFilter:error", {error: e, source:eventFilter.source});
1471
+ return true;
1472
+ }
1473
+ }
1474
+ return false;
1475
+ }
1476
+
1477
+ function addEventListener(elt, handler, nodeData, triggerSpec, explicitCancel) {
1478
+ var elementData = getInternalData(elt);
1479
+ var eltsToListenOn;
1480
+ if (triggerSpec.from) {
1481
+ eltsToListenOn = querySelectorAllExt(elt, triggerSpec.from);
1482
+ } else {
1483
+ eltsToListenOn = [elt];
1484
+ }
1485
+ // store the initial values of the elements, so we can tell if they change
1486
+ if (triggerSpec.changed) {
1487
+ eltsToListenOn.forEach(function (eltToListenOn) {
1488
+ var eltToListenOnData = getInternalData(eltToListenOn);
1489
+ eltToListenOnData.lastValue = eltToListenOn.value;
1490
+ })
1491
+ }
1492
+ forEach(eltsToListenOn, function (eltToListenOn) {
1493
+ var eventListener = function (evt) {
1494
+ if (!bodyContains(elt)) {
1495
+ eltToListenOn.removeEventListener(triggerSpec.trigger, eventListener);
1496
+ return;
1497
+ }
1498
+ if (ignoreBoostedAnchorCtrlClick(elt, evt)) {
1499
+ return;
1500
+ }
1501
+ if (explicitCancel || shouldCancel(evt, elt)) {
1502
+ evt.preventDefault();
1503
+ }
1504
+ if (maybeFilterEvent(triggerSpec, elt, evt)) {
1505
+ return;
1506
+ }
1507
+ var eventData = getInternalData(evt);
1508
+ eventData.triggerSpec = triggerSpec;
1509
+ if (eventData.handledFor == null) {
1510
+ eventData.handledFor = [];
1511
+ }
1512
+ if (eventData.handledFor.indexOf(elt) < 0) {
1513
+ eventData.handledFor.push(elt);
1514
+ if (triggerSpec.consume) {
1515
+ evt.stopPropagation();
1516
+ }
1517
+ if (triggerSpec.target && evt.target) {
1518
+ if (!matches(evt.target, triggerSpec.target)) {
1519
+ return;
1520
+ }
1521
+ }
1522
+ if (triggerSpec.once) {
1523
+ if (elementData.triggeredOnce) {
1524
+ return;
1525
+ } else {
1526
+ elementData.triggeredOnce = true;
1527
+ }
1528
+ }
1529
+ if (triggerSpec.changed) {
1530
+ var eltToListenOnData = getInternalData(eltToListenOn)
1531
+ if (eltToListenOnData.lastValue === eltToListenOn.value) {
1532
+ return;
1533
+ }
1534
+ eltToListenOnData.lastValue = eltToListenOn.value
1535
+ }
1536
+ if (elementData.delayed) {
1537
+ clearTimeout(elementData.delayed);
1538
+ }
1539
+ if (elementData.throttle) {
1540
+ return;
1541
+ }
1542
+
1543
+ if (triggerSpec.throttle > 0) {
1544
+ if (!elementData.throttle) {
1545
+ handler(elt, evt);
1546
+ elementData.throttle = setTimeout(function () {
1547
+ elementData.throttle = null;
1548
+ }, triggerSpec.throttle);
1549
+ }
1550
+ } else if (triggerSpec.delay > 0) {
1551
+ elementData.delayed = setTimeout(function() { handler(elt, evt) }, triggerSpec.delay);
1552
+ } else {
1553
+ triggerEvent(elt, 'htmx:trigger')
1554
+ handler(elt, evt);
1555
+ }
1556
+ }
1557
+ };
1558
+ if (nodeData.listenerInfos == null) {
1559
+ nodeData.listenerInfos = [];
1560
+ }
1561
+ nodeData.listenerInfos.push({
1562
+ trigger: triggerSpec.trigger,
1563
+ listener: eventListener,
1564
+ on: eltToListenOn
1565
+ })
1566
+ eltToListenOn.addEventListener(triggerSpec.trigger, eventListener);
1567
+ });
1568
+ }
1569
+
1570
+ var windowIsScrolling = false // used by initScrollHandler
1571
+ var scrollHandler = null;
1572
+ function initScrollHandler() {
1573
+ if (!scrollHandler) {
1574
+ scrollHandler = function() {
1575
+ windowIsScrolling = true
1576
+ };
1577
+ window.addEventListener("scroll", scrollHandler)
1578
+ setInterval(function() {
1579
+ if (windowIsScrolling) {
1580
+ windowIsScrolling = false;
1581
+ forEach(getDocument().querySelectorAll("[hx-trigger='revealed'],[data-hx-trigger='revealed']"), function (elt) {
1582
+ maybeReveal(elt);
1583
+ })
1584
+ }
1585
+ }, 200);
1586
+ }
1587
+ }
1588
+
1589
+ function maybeReveal(elt) {
1590
+ if (!hasAttribute(elt,'data-hx-revealed') && isScrolledIntoView(elt)) {
1591
+ elt.setAttribute('data-hx-revealed', 'true');
1592
+ var nodeData = getInternalData(elt);
1593
+ if (nodeData.initHash) {
1594
+ triggerEvent(elt, 'revealed');
1595
+ } else {
1596
+ // if the node isn't initialized, wait for it before triggering the request
1597
+ elt.addEventListener("htmx:afterProcessNode", function(evt) { triggerEvent(elt, 'revealed') }, {once: true});
1598
+ }
1599
+ }
1600
+ }
1601
+
1602
+ //====================================================================
1603
+ // Web Sockets
1604
+ //====================================================================
1605
+
1606
+ function processWebSocketInfo(elt, nodeData, info) {
1607
+ var values = splitOnWhitespace(info);
1608
+ for (var i = 0; i < values.length; i++) {
1609
+ var value = values[i].split(/:(.+)/);
1610
+ if (value[0] === "connect") {
1611
+ ensureWebSocket(elt, value[1], 0);
1612
+ }
1613
+ if (value[0] === "send") {
1614
+ processWebSocketSend(elt);
1615
+ }
1616
+ }
1617
+ }
1618
+
1619
+ function ensureWebSocket(elt, wssSource, retryCount) {
1620
+ if (!bodyContains(elt)) {
1621
+ return; // stop ensuring websocket connection when socket bearing element ceases to exist
1622
+ }
1623
+
1624
+ if (wssSource.indexOf("/") == 0) { // complete absolute paths only
1625
+ var base_part = location.hostname + (location.port ? ':'+location.port: '');
1626
+ if (location.protocol == 'https:') {
1627
+ wssSource = "wss://" + base_part + wssSource;
1628
+ } else if (location.protocol == 'http:') {
1629
+ wssSource = "ws://" + base_part + wssSource;
1630
+ }
1631
+ }
1632
+ var socket = htmx.createWebSocket(wssSource);
1633
+ socket.onerror = function (e) {
1634
+ triggerErrorEvent(elt, "htmx:wsError", {error:e, socket:socket});
1635
+ maybeCloseWebSocketSource(elt);
1636
+ };
1637
+
1638
+ socket.onclose = function (e) {
1639
+ if ([1006, 1012, 1013].indexOf(e.code) >= 0) { // Abnormal Closure/Service Restart/Try Again Later
1640
+ var delay = getWebSocketReconnectDelay(retryCount);
1641
+ setTimeout(function() {
1642
+ ensureWebSocket(elt, wssSource, retryCount+1); // creates a websocket with a new timeout
1643
+ }, delay);
1644
+ }
1645
+ };
1646
+ socket.onopen = function (e) {
1647
+ retryCount = 0;
1648
+ }
1649
+
1650
+ getInternalData(elt).webSocket = socket;
1651
+ socket.addEventListener('message', function (event) {
1652
+ if (maybeCloseWebSocketSource(elt)) {
1653
+ return;
1654
+ }
1655
+
1656
+ var response = event.data;
1657
+ withExtensions(elt, function(extension){
1658
+ response = extension.transformResponse(response, null, elt);
1659
+ });
1660
+
1661
+ var settleInfo = makeSettleInfo(elt);
1662
+ var fragment = makeFragment(response);
1663
+ var children = toArray(fragment.children);
1664
+ for (var i = 0; i < children.length; i++) {
1665
+ var child = children[i];
1666
+ oobSwap(getAttributeValue(child, "hx-swap-oob") || "true", child, settleInfo);
1667
+ }
1668
+
1669
+ settleImmediately(settleInfo.tasks);
1670
+ });
1671
+ }
1672
+
1673
+ function maybeCloseWebSocketSource(elt) {
1674
+ if (!bodyContains(elt)) {
1675
+ getInternalData(elt).webSocket.close();
1676
+ return true;
1677
+ }
1678
+ }
1679
+
1680
+ function processWebSocketSend(elt) {
1681
+ var webSocketSourceElt = getClosestMatch(elt, function (parent) {
1682
+ return getInternalData(parent).webSocket != null;
1683
+ });
1684
+ if (webSocketSourceElt) {
1685
+ elt.addEventListener(getTriggerSpecs(elt)[0].trigger, function (evt) {
1686
+ var webSocket = getInternalData(webSocketSourceElt).webSocket;
1687
+ var headers = getHeaders(elt, webSocketSourceElt);
1688
+ var results = getInputValues(elt, 'post');
1689
+ var errors = results.errors;
1690
+ var rawParameters = results.values;
1691
+ var expressionVars = getExpressionVars(elt);
1692
+ var allParameters = mergeObjects(rawParameters, expressionVars);
1693
+ var filteredParameters = filterValues(allParameters, elt);
1694
+ filteredParameters['HEADERS'] = headers;
1695
+ if (errors && errors.length > 0) {
1696
+ triggerEvent(elt, 'htmx:validation:halted', errors);
1697
+ return;
1698
+ }
1699
+ webSocket.send(JSON.stringify(filteredParameters));
1700
+ if(shouldCancel(evt, elt)){
1701
+ evt.preventDefault();
1702
+ }
1703
+ });
1704
+ } else {
1705
+ triggerErrorEvent(elt, "htmx:noWebSocketSourceError");
1706
+ }
1707
+ }
1708
+
1709
+ function getWebSocketReconnectDelay(retryCount) {
1710
+ var delay = htmx.config.wsReconnectDelay;
1711
+ if (typeof delay === 'function') {
1712
+ // @ts-ignore
1713
+ return delay(retryCount);
1714
+ }
1715
+ if (delay === 'full-jitter') {
1716
+ var exp = Math.min(retryCount, 6);
1717
+ var maxDelay = 1000 * Math.pow(2, exp);
1718
+ return maxDelay * Math.random();
1719
+ }
1720
+ logError('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"');
1721
+ }
1722
+
1723
+ //====================================================================
1724
+ // Server Sent Events
1725
+ //====================================================================
1726
+
1727
+ function processSSEInfo(elt, nodeData, info) {
1728
+ var values = splitOnWhitespace(info);
1729
+ for (var i = 0; i < values.length; i++) {
1730
+ var value = values[i].split(/:(.+)/);
1731
+ if (value[0] === "connect") {
1732
+ processSSESource(elt, value[1]);
1733
+ }
1734
+
1735
+ if ((value[0] === "swap")) {
1736
+ processSSESwap(elt, value[1])
1737
+ }
1738
+ }
1739
+ }
1740
+
1741
+ function processSSESource(elt, sseSrc) {
1742
+ var source = htmx.createEventSource(sseSrc);
1743
+ source.onerror = function (e) {
1744
+ triggerErrorEvent(elt, "htmx:sseError", {error:e, source:source});
1745
+ maybeCloseSSESource(elt);
1746
+ };
1747
+ getInternalData(elt).sseEventSource = source;
1748
+ }
1749
+
1750
+ function processSSESwap(elt, sseEventName) {
1751
+ var sseSourceElt = getClosestMatch(elt, hasEventSource);
1752
+ if (sseSourceElt) {
1753
+ var sseEventSource = getInternalData(sseSourceElt).sseEventSource;
1754
+ var sseListener = function (event) {
1755
+ if (maybeCloseSSESource(sseSourceElt)) {
1756
+ return;
1757
+ }
1758
+ if (!bodyContains(elt)) {
1759
+ sseEventSource.removeEventListener(sseEventName, sseListener);
1760
+ return;
1761
+ }
1762
+
1763
+ ///////////////////////////
1764
+ // TODO: merge this code with AJAX and WebSockets code in the future.
1765
+
1766
+ var response = event.data;
1767
+ withExtensions(elt, function(extension){
1768
+ response = extension.transformResponse(response, null, elt);
1769
+ });
1770
+
1771
+ var swapSpec = getSwapSpecification(elt)
1772
+ var target = getTarget(elt)
1773
+ var settleInfo = makeSettleInfo(elt);
1774
+
1775
+ selectAndSwap(swapSpec.swapStyle, target, elt, response, settleInfo)
1776
+ settleImmediately(settleInfo.tasks)
1777
+ triggerEvent(elt, "htmx:sseMessage", event)
1778
+ };
1779
+
1780
+ getInternalData(elt).sseListener = sseListener;
1781
+ sseEventSource.addEventListener(sseEventName, sseListener);
1782
+ } else {
1783
+ triggerErrorEvent(elt, "htmx:noSSESourceError");
1784
+ }
1785
+ }
1786
+
1787
+ function processSSETrigger(elt, handler, sseEventName) {
1788
+ var sseSourceElt = getClosestMatch(elt, hasEventSource);
1789
+ if (sseSourceElt) {
1790
+ var sseEventSource = getInternalData(sseSourceElt).sseEventSource;
1791
+ var sseListener = function () {
1792
+ if (!maybeCloseSSESource(sseSourceElt)) {
1793
+ if (bodyContains(elt)) {
1794
+ handler(elt);
1795
+ } else {
1796
+ sseEventSource.removeEventListener(sseEventName, sseListener);
1797
+ }
1798
+ }
1799
+ };
1800
+ getInternalData(elt).sseListener = sseListener;
1801
+ sseEventSource.addEventListener(sseEventName, sseListener);
1802
+ } else {
1803
+ triggerErrorEvent(elt, "htmx:noSSESourceError");
1804
+ }
1805
+ }
1806
+
1807
+ function maybeCloseSSESource(elt) {
1808
+ if (!bodyContains(elt)) {
1809
+ getInternalData(elt).sseEventSource.close();
1810
+ return true;
1811
+ }
1812
+ }
1813
+
1814
+ function hasEventSource(node) {
1815
+ return getInternalData(node).sseEventSource != null;
1816
+ }
1817
+
1818
+ //====================================================================
1819
+
1820
+ function loadImmediately(elt, handler, nodeData, delay) {
1821
+ var load = function(){
1822
+ if (!nodeData.loaded) {
1823
+ nodeData.loaded = true;
1824
+ handler(elt);
1825
+ }
1826
+ }
1827
+ if (delay > 0) {
1828
+ setTimeout(load, delay);
1829
+ } else {
1830
+ load();
1831
+ }
1832
+ }
1833
+
1834
+ function processVerbs(elt, nodeData, triggerSpecs) {
1835
+ var explicitAction = false;
1836
+ forEach(VERBS, function (verb) {
1837
+ if (hasAttribute(elt,'hx-' + verb)) {
1838
+ var path = getAttributeValue(elt, 'hx-' + verb);
1839
+ explicitAction = true;
1840
+ nodeData.path = path;
1841
+ nodeData.verb = verb;
1842
+ triggerSpecs.forEach(function(triggerSpec) {
1843
+ addTriggerHandler(elt, triggerSpec, nodeData, function (elt, evt) {
1844
+ if (closest(elt, htmx.config.disableSelector)) {
1845
+ cleanUpElement(elt)
1846
+ return
1847
+ }
1848
+ issueAjaxRequest(verb, path, elt, evt)
1849
+ })
1850
+ });
1851
+ }
1852
+ });
1853
+ return explicitAction;
1854
+ }
1855
+
1856
+ function addTriggerHandler(elt, triggerSpec, nodeData, handler) {
1857
+ if (triggerSpec.sseEvent) {
1858
+ processSSETrigger(elt, handler, triggerSpec.sseEvent);
1859
+ } else if (triggerSpec.trigger === "revealed") {
1860
+ initScrollHandler();
1861
+ addEventListener(elt, handler, nodeData, triggerSpec);
1862
+ maybeReveal(elt);
1863
+ } else if (triggerSpec.trigger === "intersect") {
1864
+ var observerOptions = {};
1865
+ if (triggerSpec.root) {
1866
+ observerOptions.root = querySelectorExt(elt, triggerSpec.root)
1867
+ }
1868
+ if (triggerSpec.threshold) {
1869
+ observerOptions.threshold = parseFloat(triggerSpec.threshold);
1870
+ }
1871
+ var observer = new IntersectionObserver(function (entries) {
1872
+ for (var i = 0; i < entries.length; i++) {
1873
+ var entry = entries[i];
1874
+ if (entry.isIntersecting) {
1875
+ triggerEvent(elt, "intersect");
1876
+ break;
1877
+ }
1878
+ }
1879
+ }, observerOptions);
1880
+ observer.observe(elt);
1881
+ addEventListener(elt, handler, nodeData, triggerSpec);
1882
+ } else if (triggerSpec.trigger === "load") {
1883
+ if (!maybeFilterEvent(triggerSpec, elt, makeEvent("load", {elt: elt}))) {
1884
+ loadImmediately(elt, handler, nodeData, triggerSpec.delay);
1885
+ }
1886
+ } else if (triggerSpec.pollInterval > 0) {
1887
+ nodeData.polling = true;
1888
+ processPolling(elt, handler, triggerSpec);
1889
+ } else {
1890
+ addEventListener(elt, handler, nodeData, triggerSpec);
1891
+ }
1892
+ }
1893
+
1894
+ function evalScript(script) {
1895
+ if (htmx.config.allowScriptTags && (script.type === "text/javascript" || script.type === "module" || script.type === "") ) {
1896
+ var newScript = getDocument().createElement("script");
1897
+ forEach(script.attributes, function (attr) {
1898
+ newScript.setAttribute(attr.name, attr.value);
1899
+ });
1900
+ newScript.textContent = script.textContent;
1901
+ newScript.async = false;
1902
+ if (htmx.config.inlineScriptNonce) {
1903
+ newScript.nonce = htmx.config.inlineScriptNonce;
1904
+ }
1905
+ var parent = script.parentElement;
1906
+
1907
+ try {
1908
+ parent.insertBefore(newScript, script);
1909
+ } catch (e) {
1910
+ logError(e);
1911
+ } finally {
1912
+ // remove old script element, but only if it is still in DOM
1913
+ if (script.parentElement) {
1914
+ script.parentElement.removeChild(script);
1915
+ }
1916
+ }
1917
+ }
1918
+ }
1919
+
1920
+ function processScripts(elt) {
1921
+ if (matches(elt, "script")) {
1922
+ evalScript(elt);
1923
+ }
1924
+ forEach(findAll(elt, "script"), function (script) {
1925
+ evalScript(script);
1926
+ });
1927
+ }
1928
+
1929
+ function shouldProcessHxOn(elt) {
1930
+ var attributes = elt.attributes
1931
+ for (var j = 0; j < attributes.length; j++) {
1932
+ var attrName = attributes[j].name
1933
+ if (startsWith(attrName, "hx-on:") || startsWith(attrName, "data-hx-on:") ||
1934
+ startsWith(attrName, "hx-on-") || startsWith(attrName, "data-hx-on-")) {
1935
+ return true
1936
+ }
1937
+ }
1938
+ return false
1939
+ }
1940
+
1941
+ function findHxOnWildcardElements(elt) {
1942
+ var node = null
1943
+ var elements = []
1944
+
1945
+ if (shouldProcessHxOn(elt)) {
1946
+ elements.push(elt)
1947
+ }
1948
+
1949
+ if (document.evaluate) {
1950
+ var iter = document.evaluate('.//*[@*[ starts-with(name(), "hx-on:") or starts-with(name(), "data-hx-on:") or' +
1951
+ ' starts-with(name(), "hx-on-") or starts-with(name(), "data-hx-on-") ]]', elt)
1952
+ while (node = iter.iterateNext()) elements.push(node)
1953
+ } else {
1954
+ var allElements = elt.getElementsByTagName("*")
1955
+ for (var i = 0; i < allElements.length; i++) {
1956
+ if (shouldProcessHxOn(allElements[i])) {
1957
+ elements.push(allElements[i])
1958
+ }
1959
+ }
1960
+ }
1961
+
1962
+ return elements
1963
+ }
1964
+
1965
+ function findElementsToProcess(elt) {
1966
+ if (elt.querySelectorAll) {
1967
+ var boostedSelector = ", [hx-boost] a, [data-hx-boost] a, a[hx-boost], a[data-hx-boost]";
1968
+ var results = elt.querySelectorAll(VERB_SELECTOR + boostedSelector + ", form, [type='submit'], [hx-sse], [data-hx-sse], [hx-ws]," +
1969
+ " [data-hx-ws], [hx-ext], [data-hx-ext], [hx-trigger], [data-hx-trigger], [hx-on], [data-hx-on]");
1970
+ return results;
1971
+ } else {
1972
+ return [];
1973
+ }
1974
+ }
1975
+
1976
+ // Handle submit buttons/inputs that have the form attribute set
1977
+ // see https://developer.mozilla.org/docs/Web/HTML/Element/button
1978
+ function maybeSetLastButtonClicked(evt) {
1979
+ var elt = closest(evt.target, "button, input[type='submit']");
1980
+ var internalData = getRelatedFormData(evt)
1981
+ if (internalData) {
1982
+ internalData.lastButtonClicked = elt;
1983
+ }
1984
+ };
1985
+ function maybeUnsetLastButtonClicked(evt){
1986
+ var internalData = getRelatedFormData(evt)
1987
+ if (internalData) {
1988
+ internalData.lastButtonClicked = null;
1989
+ }
1990
+ }
1991
+ function getRelatedFormData(evt) {
1992
+ var elt = closest(evt.target, "button, input[type='submit']");
1993
+ if (!elt) {
1994
+ return;
1995
+ }
1996
+ var form = resolveTarget('#' + getRawAttribute(elt, 'form')) || closest(elt, 'form');
1997
+ if (!form) {
1998
+ return;
1999
+ }
2000
+ return getInternalData(form);
2001
+ }
2002
+ function initButtonTracking(elt) {
2003
+ // need to handle both click and focus in:
2004
+ // focusin - in case someone tabs in to a button and hits the space bar
2005
+ // click - on OSX buttons do not focus on click see https://bugs.webkit.org/show_bug.cgi?id=13724
2006
+ elt.addEventListener('click', maybeSetLastButtonClicked)
2007
+ elt.addEventListener('focusin', maybeSetLastButtonClicked)
2008
+ elt.addEventListener('focusout', maybeUnsetLastButtonClicked)
2009
+ }
2010
+
2011
+ function countCurlies(line) {
2012
+ var tokens = tokenizeString(line);
2013
+ var netCurlies = 0;
2014
+ for (var i = 0; i < tokens.length; i++) {
2015
+ const token = tokens[i];
2016
+ if (token === "{") {
2017
+ netCurlies++;
2018
+ } else if (token === "}") {
2019
+ netCurlies--;
2020
+ }
2021
+ }
2022
+ return netCurlies;
2023
+ }
2024
+
2025
+ function addHxOnEventHandler(elt, eventName, code) {
2026
+ var nodeData = getInternalData(elt);
2027
+ if (!Array.isArray(nodeData.onHandlers)) {
2028
+ nodeData.onHandlers = [];
2029
+ }
2030
+ var func;
2031
+ var listener = function (e) {
2032
+ return maybeEval(elt, function() {
2033
+ if (!func) {
2034
+ func = new Function("event", code);
2035
+ }
2036
+ func.call(elt, e);
2037
+ });
2038
+ };
2039
+ elt.addEventListener(eventName, listener);
2040
+ nodeData.onHandlers.push({event:eventName, listener:listener});
2041
+ }
2042
+
2043
+ function processHxOn(elt) {
2044
+ var hxOnValue = getAttributeValue(elt, 'hx-on');
2045
+ if (hxOnValue) {
2046
+ var handlers = {}
2047
+ var lines = hxOnValue.split("\n");
2048
+ var currentEvent = null;
2049
+ var curlyCount = 0;
2050
+ while (lines.length > 0) {
2051
+ var line = lines.shift();
2052
+ var match = line.match(/^\s*([a-zA-Z:\-\.]+:)(.*)/);
2053
+ if (curlyCount === 0 && match) {
2054
+ line.split(":")
2055
+ currentEvent = match[1].slice(0, -1); // strip last colon
2056
+ handlers[currentEvent] = match[2];
2057
+ } else {
2058
+ handlers[currentEvent] += line;
2059
+ }
2060
+ curlyCount += countCurlies(line);
2061
+ }
2062
+
2063
+ for (var eventName in handlers) {
2064
+ addHxOnEventHandler(elt, eventName, handlers[eventName]);
2065
+ }
2066
+ }
2067
+ }
2068
+
2069
+ function processHxOnWildcard(elt) {
2070
+ // wipe any previous on handlers so that this function takes precedence
2071
+ deInitOnHandlers(elt)
2072
+
2073
+ for (var i = 0; i < elt.attributes.length; i++) {
2074
+ var name = elt.attributes[i].name
2075
+ var value = elt.attributes[i].value
2076
+ if (startsWith(name, "hx-on") || startsWith(name, "data-hx-on")) {
2077
+ var afterOnPosition = name.indexOf("-on") + 3;
2078
+ var nextChar = name.slice(afterOnPosition, afterOnPosition + 1);
2079
+ if (nextChar === "-" || nextChar === ":") {
2080
+ var eventName = name.slice(afterOnPosition + 1);
2081
+ // if the eventName starts with a colon or dash, prepend "htmx" for shorthand support
2082
+ if (startsWith(eventName, ":")) {
2083
+ eventName = "htmx" + eventName
2084
+ } else if (startsWith(eventName, "-")) {
2085
+ eventName = "htmx:" + eventName.slice(1);
2086
+ } else if (startsWith(eventName, "htmx-")) {
2087
+ eventName = "htmx:" + eventName.slice(5);
2088
+ }
2089
+
2090
+ addHxOnEventHandler(elt, eventName, value)
2091
+ }
2092
+ }
2093
+ }
2094
+ }
2095
+
2096
+ function initNode(elt) {
2097
+ if (closest(elt, htmx.config.disableSelector)) {
2098
+ cleanUpElement(elt)
2099
+ return;
2100
+ }
2101
+ var nodeData = getInternalData(elt);
2102
+ if (nodeData.initHash !== attributeHash(elt)) {
2103
+ // clean up any previously processed info
2104
+ deInitNode(elt);
2105
+
2106
+ nodeData.initHash = attributeHash(elt);
2107
+
2108
+ processHxOn(elt);
2109
+
2110
+ triggerEvent(elt, "htmx:beforeProcessNode")
2111
+
2112
+ if (elt.value) {
2113
+ nodeData.lastValue = elt.value;
2114
+ }
2115
+
2116
+ var triggerSpecs = getTriggerSpecs(elt);
2117
+ var hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs);
2118
+
2119
+ if (!hasExplicitHttpAction) {
2120
+ if (getClosestAttributeValue(elt, "hx-boost") === "true") {
2121
+ boostElement(elt, nodeData, triggerSpecs);
2122
+ } else if (hasAttribute(elt, 'hx-trigger')) {
2123
+ triggerSpecs.forEach(function (triggerSpec) {
2124
+ // For "naked" triggers, don't do anything at all
2125
+ addTriggerHandler(elt, triggerSpec, nodeData, function () {
2126
+ })
2127
+ })
2128
+ }
2129
+ }
2130
+
2131
+ // Handle submit buttons/inputs that have the form attribute set
2132
+ // see https://developer.mozilla.org/docs/Web/HTML/Element/button
2133
+ if (elt.tagName === "FORM" || (getRawAttribute(elt, "type") === "submit" && hasAttribute(elt, "form"))) {
2134
+ initButtonTracking(elt)
2135
+ }
2136
+
2137
+ var sseInfo = getAttributeValue(elt, 'hx-sse');
2138
+ if (sseInfo) {
2139
+ processSSEInfo(elt, nodeData, sseInfo);
2140
+ }
2141
+
2142
+ var wsInfo = getAttributeValue(elt, 'hx-ws');
2143
+ if (wsInfo) {
2144
+ processWebSocketInfo(elt, nodeData, wsInfo);
2145
+ }
2146
+ triggerEvent(elt, "htmx:afterProcessNode");
2147
+ }
2148
+ }
2149
+
2150
+ function processNode(elt) {
2151
+ elt = resolveTarget(elt);
2152
+ if (closest(elt, htmx.config.disableSelector)) {
2153
+ cleanUpElement(elt)
2154
+ return;
2155
+ }
2156
+ initNode(elt);
2157
+ forEach(findElementsToProcess(elt), function(child) { initNode(child) });
2158
+ // Because it happens second, the new way of adding onHandlers superseeds the old one
2159
+ // i.e. if there are any hx-on:eventName attributes, the hx-on attribute will be ignored
2160
+ forEach(findHxOnWildcardElements(elt), processHxOnWildcard);
2161
+ }
2162
+
2163
+ //====================================================================
2164
+ // Event/Log Support
2165
+ //====================================================================
2166
+
2167
+ function kebabEventName(str) {
2168
+ return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
2169
+ }
2170
+
2171
+ function makeEvent(eventName, detail) {
2172
+ var evt;
2173
+ if (window.CustomEvent && typeof window.CustomEvent === 'function') {
2174
+ evt = new CustomEvent(eventName, {bubbles: true, cancelable: true, detail: detail});
2175
+ } else {
2176
+ evt = getDocument().createEvent('CustomEvent');
2177
+ evt.initCustomEvent(eventName, true, true, detail);
2178
+ }
2179
+ return evt;
2180
+ }
2181
+
2182
+ function triggerErrorEvent(elt, eventName, detail) {
2183
+ triggerEvent(elt, eventName, mergeObjects({error:eventName}, detail));
2184
+ }
2185
+
2186
+ function ignoreEventForLogging(eventName) {
2187
+ return eventName === "htmx:afterProcessNode"
2188
+ }
2189
+
2190
+ /**
2191
+ * `withExtensions` locates all active extensions for a provided element, then
2192
+ * executes the provided function using each of the active extensions. It should
2193
+ * be called internally at every extendable execution point in htmx.
2194
+ *
2195
+ * @param {HTMLElement} elt
2196
+ * @param {(extension:import("./htmx").HtmxExtension) => void} toDo
2197
+ * @returns void
2198
+ */
2199
+ function withExtensions(elt, toDo) {
2200
+ forEach(getExtensions(elt), function(extension){
2201
+ try {
2202
+ toDo(extension);
2203
+ } catch (e) {
2204
+ logError(e);
2205
+ }
2206
+ });
2207
+ }
2208
+
2209
+ function logError(msg) {
2210
+ if(console.error) {
2211
+ console.error(msg);
2212
+ } else if (console.log) {
2213
+ console.log("ERROR: ", msg);
2214
+ }
2215
+ }
2216
+
2217
+ function triggerEvent(elt, eventName, detail) {
2218
+ elt = resolveTarget(elt);
2219
+ if (detail == null) {
2220
+ detail = {};
2221
+ }
2222
+ detail["elt"] = elt;
2223
+ var event = makeEvent(eventName, detail);
2224
+ if (htmx.logger && !ignoreEventForLogging(eventName)) {
2225
+ htmx.logger(elt, eventName, detail);
2226
+ }
2227
+ if (detail.error) {
2228
+ logError(detail.error);
2229
+ triggerEvent(elt, "htmx:error", {errorInfo:detail})
2230
+ }
2231
+ var eventResult = elt.dispatchEvent(event);
2232
+ var kebabName = kebabEventName(eventName);
2233
+ if (eventResult && kebabName !== eventName) {
2234
+ var kebabedEvent = makeEvent(kebabName, event.detail);
2235
+ eventResult = eventResult && elt.dispatchEvent(kebabedEvent)
2236
+ }
2237
+ withExtensions(elt, function (extension) {
2238
+ eventResult = eventResult && (extension.onEvent(eventName, event) !== false && !event.defaultPrevented)
2239
+ });
2240
+ return eventResult;
2241
+ }
2242
+
2243
+ //====================================================================
2244
+ // History Support
2245
+ //====================================================================
2246
+ var currentPathForHistory = location.pathname+location.search;
2247
+
2248
+ function getHistoryElement() {
2249
+ var historyElt = getDocument().querySelector('[hx-history-elt],[data-hx-history-elt]');
2250
+ return historyElt || getDocument().body;
2251
+ }
2252
+
2253
+ function saveToHistoryCache(url, content, title, scroll) {
2254
+ if (!canAccessLocalStorage()) {
2255
+ return;
2256
+ }
2257
+
2258
+ if (htmx.config.historyCacheSize <= 0) {
2259
+ // make sure that an eventually already existing cache is purged
2260
+ localStorage.removeItem("htmx-history-cache");
2261
+ return;
2262
+ }
2263
+
2264
+ url = normalizePath(url);
2265
+
2266
+ var historyCache = parseJSON(localStorage.getItem("htmx-history-cache")) || [];
2267
+ for (var i = 0; i < historyCache.length; i++) {
2268
+ if (historyCache[i].url === url) {
2269
+ historyCache.splice(i, 1);
2270
+ break;
2271
+ }
2272
+ }
2273
+ var newHistoryItem = {url:url, content: content, title:title, scroll:scroll};
2274
+ triggerEvent(getDocument().body, "htmx:historyItemCreated", {item:newHistoryItem, cache: historyCache})
2275
+ historyCache.push(newHistoryItem)
2276
+ while (historyCache.length > htmx.config.historyCacheSize) {
2277
+ historyCache.shift();
2278
+ }
2279
+ while(historyCache.length > 0){
2280
+ try {
2281
+ localStorage.setItem("htmx-history-cache", JSON.stringify(historyCache));
2282
+ break;
2283
+ } catch (e) {
2284
+ triggerErrorEvent(getDocument().body, "htmx:historyCacheError", {cause:e, cache: historyCache})
2285
+ historyCache.shift(); // shrink the cache and retry
2286
+ }
2287
+ }
2288
+ }
2289
+
2290
+ function getCachedHistory(url) {
2291
+ if (!canAccessLocalStorage()) {
2292
+ return null;
2293
+ }
2294
+
2295
+ url = normalizePath(url);
2296
+
2297
+ var historyCache = parseJSON(localStorage.getItem("htmx-history-cache")) || [];
2298
+ for (var i = 0; i < historyCache.length; i++) {
2299
+ if (historyCache[i].url === url) {
2300
+ return historyCache[i];
2301
+ }
2302
+ }
2303
+ return null;
2304
+ }
2305
+
2306
+ function cleanInnerHtmlForHistory(elt) {
2307
+ var className = htmx.config.requestClass;
2308
+ var clone = elt.cloneNode(true);
2309
+ forEach(findAll(clone, "." + className), function(child){
2310
+ removeClassFromElement(child, className);
2311
+ });
2312
+ return clone.innerHTML;
2313
+ }
2314
+
2315
+ function saveCurrentPageToHistory() {
2316
+ var elt = getHistoryElement();
2317
+ var path = currentPathForHistory || location.pathname+location.search;
2318
+
2319
+ // Allow history snapshot feature to be disabled where hx-history="false"
2320
+ // is present *anywhere* in the current document we're about to save,
2321
+ // so we can prevent privileged data entering the cache.
2322
+ // The page will still be reachable as a history entry, but htmx will fetch it
2323
+ // live from the server onpopstate rather than look in the localStorage cache
2324
+ var disableHistoryCache
2325
+ try {
2326
+ disableHistoryCache = getDocument().querySelector('[hx-history="false" i],[data-hx-history="false" i]')
2327
+ } catch (e) {
2328
+ // IE11: insensitive modifier not supported so fallback to case sensitive selector
2329
+ disableHistoryCache = getDocument().querySelector('[hx-history="false"],[data-hx-history="false"]')
2330
+ }
2331
+ if (!disableHistoryCache) {
2332
+ triggerEvent(getDocument().body, "htmx:beforeHistorySave", {path: path, historyElt: elt});
2333
+ saveToHistoryCache(path, cleanInnerHtmlForHistory(elt), getDocument().title, window.scrollY);
2334
+ }
2335
+
2336
+ if (htmx.config.historyEnabled) history.replaceState({htmx: true}, getDocument().title, window.location.href);
2337
+ }
2338
+
2339
+ function pushUrlIntoHistory(path) {
2340
+ // remove the cache buster parameter, if any
2341
+ if (htmx.config.getCacheBusterParam) {
2342
+ path = path.replace(/org\.htmx\.cache-buster=[^&]*&?/, '')
2343
+ if (endsWith(path, '&') || endsWith(path, "?")) {
2344
+ path = path.slice(0, -1);
2345
+ }
2346
+ }
2347
+ if(htmx.config.historyEnabled) {
2348
+ history.pushState({htmx:true}, "", path);
2349
+ }
2350
+ currentPathForHistory = path;
2351
+ }
2352
+
2353
+ function replaceUrlInHistory(path) {
2354
+ if(htmx.config.historyEnabled) history.replaceState({htmx:true}, "", path);
2355
+ currentPathForHistory = path;
2356
+ }
2357
+
2358
+ function settleImmediately(tasks) {
2359
+ forEach(tasks, function (task) {
2360
+ task.call();
2361
+ });
2362
+ }
2363
+
2364
+ function loadHistoryFromServer(path) {
2365
+ var request = new XMLHttpRequest();
2366
+ var details = {path: path, xhr:request};
2367
+ triggerEvent(getDocument().body, "htmx:historyCacheMiss", details);
2368
+ request.open('GET', path, true);
2369
+ request.setRequestHeader("HX-Request", "true");
2370
+ request.setRequestHeader("HX-History-Restore-Request", "true");
2371
+ request.setRequestHeader("HX-Current-URL", getDocument().location.href);
2372
+ request.onload = function () {
2373
+ if (this.status >= 200 && this.status < 400) {
2374
+ triggerEvent(getDocument().body, "htmx:historyCacheMissLoad", details);
2375
+ var fragment = makeFragment(this.response);
2376
+ // @ts-ignore
2377
+ fragment = fragment.querySelector('[hx-history-elt],[data-hx-history-elt]') || fragment;
2378
+ var historyElement = getHistoryElement();
2379
+ var settleInfo = makeSettleInfo(historyElement);
2380
+ var title = findTitle(this.response);
2381
+ if (title) {
2382
+ var titleElt = find("title");
2383
+ if (titleElt) {
2384
+ titleElt.innerHTML = title;
2385
+ } else {
2386
+ window.document.title = title;
2387
+ }
2388
+ }
2389
+ // @ts-ignore
2390
+ swapInnerHTML(historyElement, fragment, settleInfo)
2391
+ settleImmediately(settleInfo.tasks);
2392
+ currentPathForHistory = path;
2393
+ triggerEvent(getDocument().body, "htmx:historyRestore", {path: path, cacheMiss:true, serverResponse:this.response});
2394
+ } else {
2395
+ triggerErrorEvent(getDocument().body, "htmx:historyCacheMissLoadError", details);
2396
+ }
2397
+ };
2398
+ request.send();
2399
+ }
2400
+
2401
+ function restoreHistory(path) {
2402
+ saveCurrentPageToHistory();
2403
+ path = path || location.pathname+location.search;
2404
+ var cached = getCachedHistory(path);
2405
+ if (cached) {
2406
+ var fragment = makeFragment(cached.content);
2407
+ var historyElement = getHistoryElement();
2408
+ var settleInfo = makeSettleInfo(historyElement);
2409
+ swapInnerHTML(historyElement, fragment, settleInfo)
2410
+ settleImmediately(settleInfo.tasks);
2411
+ document.title = cached.title;
2412
+ setTimeout(function () {
2413
+ window.scrollTo(0, cached.scroll);
2414
+ }, 0); // next 'tick', so browser has time to render layout
2415
+ currentPathForHistory = path;
2416
+ triggerEvent(getDocument().body, "htmx:historyRestore", {path:path, item:cached});
2417
+ } else {
2418
+ if (htmx.config.refreshOnHistoryMiss) {
2419
+
2420
+ // @ts-ignore: optional parameter in reload() function throws error
2421
+ window.location.reload(true);
2422
+ } else {
2423
+ loadHistoryFromServer(path);
2424
+ }
2425
+ }
2426
+ }
2427
+
2428
+ function addRequestIndicatorClasses(elt) {
2429
+ var indicators = findAttributeTargets(elt, 'hx-indicator');
2430
+ if (indicators == null) {
2431
+ indicators = [elt];
2432
+ }
2433
+ forEach(indicators, function (ic) {
2434
+ var internalData = getInternalData(ic);
2435
+ internalData.requestCount = (internalData.requestCount || 0) + 1;
2436
+ ic.classList["add"].call(ic.classList, htmx.config.requestClass);
2437
+ });
2438
+ return indicators;
2439
+ }
2440
+
2441
+ function disableElements(elt) {
2442
+ var disabledElts = findAttributeTargets(elt, 'hx-disabled-elt');
2443
+ if (disabledElts == null) {
2444
+ disabledElts = [];
2445
+ }
2446
+ forEach(disabledElts, function (disabledElement) {
2447
+ var internalData = getInternalData(disabledElement);
2448
+ internalData.requestCount = (internalData.requestCount || 0) + 1;
2449
+ disabledElement.setAttribute("disabled", "");
2450
+ });
2451
+ return disabledElts;
2452
+ }
2453
+
2454
+ function removeRequestIndicators(indicators, disabled) {
2455
+ forEach(indicators, function (ic) {
2456
+ var internalData = getInternalData(ic);
2457
+ internalData.requestCount = (internalData.requestCount || 0) - 1;
2458
+ if (internalData.requestCount === 0) {
2459
+ ic.classList["remove"].call(ic.classList, htmx.config.requestClass);
2460
+ }
2461
+ });
2462
+ forEach(disabled, function (disabledElement) {
2463
+ var internalData = getInternalData(disabledElement);
2464
+ internalData.requestCount = (internalData.requestCount || 0) - 1;
2465
+ if (internalData.requestCount === 0) {
2466
+ disabledElement.removeAttribute('disabled');
2467
+ }
2468
+ });
2469
+ }
2470
+
2471
+ //====================================================================
2472
+ // Input Value Processing
2473
+ //====================================================================
2474
+
2475
+ function haveSeenNode(processed, elt) {
2476
+ for (var i = 0; i < processed.length; i++) {
2477
+ var node = processed[i];
2478
+ if (node.isSameNode(elt)) {
2479
+ return true;
2480
+ }
2481
+ }
2482
+ return false;
2483
+ }
2484
+
2485
+ function shouldInclude(elt) {
2486
+ if(elt.name === "" || elt.name == null || elt.disabled || closest(elt, "fieldset[disabled]")) {
2487
+ return false;
2488
+ }
2489
+ // ignore "submitter" types (see jQuery src/serialize.js)
2490
+ if (elt.type === "button" || elt.type === "submit" || elt.tagName === "image" || elt.tagName === "reset" || elt.tagName === "file" ) {
2491
+ return false;
2492
+ }
2493
+ if (elt.type === "checkbox" || elt.type === "radio" ) {
2494
+ return elt.checked;
2495
+ }
2496
+ return true;
2497
+ }
2498
+
2499
+ function addValueToValues(name, value, values) {
2500
+ // This is a little ugly because both the current value of the named value in the form
2501
+ // and the new value could be arrays, so we have to handle all four cases :/
2502
+ if (name != null && value != null) {
2503
+ var current = values[name];
2504
+ if (current === undefined) {
2505
+ values[name] = value;
2506
+ } else if (Array.isArray(current)) {
2507
+ if (Array.isArray(value)) {
2508
+ values[name] = current.concat(value);
2509
+ } else {
2510
+ current.push(value);
2511
+ }
2512
+ } else {
2513
+ if (Array.isArray(value)) {
2514
+ values[name] = [current].concat(value);
2515
+ } else {
2516
+ values[name] = [current, value];
2517
+ }
2518
+ }
2519
+ }
2520
+ }
2521
+
2522
+ function processInputValue(processed, values, errors, elt, validate) {
2523
+ if (elt == null || haveSeenNode(processed, elt)) {
2524
+ return;
2525
+ } else {
2526
+ processed.push(elt);
2527
+ }
2528
+ if (shouldInclude(elt)) {
2529
+ var name = getRawAttribute(elt,"name");
2530
+ var value = elt.value;
2531
+ if (elt.multiple && elt.tagName === "SELECT") {
2532
+ value = toArray(elt.querySelectorAll("option:checked")).map(function (e) { return e.value });
2533
+ }
2534
+ // include file inputs
2535
+ if (elt.files) {
2536
+ value = toArray(elt.files);
2537
+ }
2538
+ addValueToValues(name, value, values);
2539
+ if (validate) {
2540
+ validateElement(elt, errors);
2541
+ }
2542
+ }
2543
+ if (matches(elt, 'form')) {
2544
+ var inputs = elt.elements;
2545
+ forEach(inputs, function(input) {
2546
+ processInputValue(processed, values, errors, input, validate);
2547
+ });
2548
+ }
2549
+ }
2550
+
2551
+ function validateElement(element, errors) {
2552
+ if (element.willValidate) {
2553
+ triggerEvent(element, "htmx:validation:validate")
2554
+ if (!element.checkValidity()) {
2555
+ errors.push({elt: element, message:element.validationMessage, validity:element.validity});
2556
+ triggerEvent(element, "htmx:validation:failed", {message:element.validationMessage, validity:element.validity})
2557
+ }
2558
+ }
2559
+ }
2560
+
2561
+ /**
2562
+ * @param {HTMLElement} elt
2563
+ * @param {string} verb
2564
+ */
2565
+ function getInputValues(elt, verb) {
2566
+ var processed = [];
2567
+ var values = {};
2568
+ var formValues = {};
2569
+ var errors = [];
2570
+ var internalData = getInternalData(elt);
2571
+ if (internalData.lastButtonClicked && !bodyContains(internalData.lastButtonClicked)) {
2572
+ internalData.lastButtonClicked = null
2573
+ }
2574
+
2575
+ // only validate when form is directly submitted and novalidate or formnovalidate are not set
2576
+ // or if the element has an explicit hx-validate="true" on it
2577
+ var validate = (matches(elt, 'form') && elt.noValidate !== true) || getAttributeValue(elt, "hx-validate") === "true";
2578
+ if (internalData.lastButtonClicked) {
2579
+ validate = validate && internalData.lastButtonClicked.formNoValidate !== true;
2580
+ }
2581
+
2582
+ // for a non-GET include the closest form
2583
+ if (verb !== 'get') {
2584
+ processInputValue(processed, formValues, errors, closest(elt, 'form'), validate);
2585
+ }
2586
+
2587
+ // include the element itself
2588
+ processInputValue(processed, values, errors, elt, validate);
2589
+
2590
+ // if a button or submit was clicked last, include its value
2591
+ if (internalData.lastButtonClicked || elt.tagName === "BUTTON" ||
2592
+ (elt.tagName === "INPUT" && getRawAttribute(elt, "type") === "submit")) {
2593
+ var button = internalData.lastButtonClicked || elt
2594
+ var name = getRawAttribute(button, "name")
2595
+ addValueToValues(name, button.value, formValues)
2596
+ }
2597
+
2598
+ // include any explicit includes
2599
+ var includes = findAttributeTargets(elt, "hx-include");
2600
+ forEach(includes, function(node) {
2601
+ processInputValue(processed, values, errors, node, validate);
2602
+ // if a non-form is included, include any input values within it
2603
+ if (!matches(node, 'form')) {
2604
+ forEach(node.querySelectorAll(INPUT_SELECTOR), function (descendant) {
2605
+ processInputValue(processed, values, errors, descendant, validate);
2606
+ })
2607
+ }
2608
+ });
2609
+
2610
+ // form values take precedence, overriding the regular values
2611
+ values = mergeObjects(values, formValues);
2612
+
2613
+ return {errors:errors, values:values};
2614
+ }
2615
+
2616
+ function appendParam(returnStr, name, realValue) {
2617
+ if (returnStr !== "") {
2618
+ returnStr += "&";
2619
+ }
2620
+ if (String(realValue) === "[object Object]") {
2621
+ realValue = JSON.stringify(realValue);
2622
+ }
2623
+ var s = encodeURIComponent(realValue);
2624
+ returnStr += encodeURIComponent(name) + "=" + s;
2625
+ return returnStr;
2626
+ }
2627
+
2628
+ function urlEncode(values) {
2629
+ var returnStr = "";
2630
+ for (var name in values) {
2631
+ if (values.hasOwnProperty(name)) {
2632
+ var value = values[name];
2633
+ if (Array.isArray(value)) {
2634
+ forEach(value, function(v) {
2635
+ returnStr = appendParam(returnStr, name, v);
2636
+ });
2637
+ } else {
2638
+ returnStr = appendParam(returnStr, name, value);
2639
+ }
2640
+ }
2641
+ }
2642
+ return returnStr;
2643
+ }
2644
+
2645
+ function makeFormData(values) {
2646
+ var formData = new FormData();
2647
+ for (var name in values) {
2648
+ if (values.hasOwnProperty(name)) {
2649
+ var value = values[name];
2650
+ if (Array.isArray(value)) {
2651
+ forEach(value, function(v) {
2652
+ formData.append(name, v);
2653
+ });
2654
+ } else {
2655
+ formData.append(name, value);
2656
+ }
2657
+ }
2658
+ }
2659
+ return formData;
2660
+ }
2661
+
2662
+ //====================================================================
2663
+ // Ajax
2664
+ //====================================================================
2665
+
2666
+ /**
2667
+ * @param {HTMLElement} elt
2668
+ * @param {HTMLElement} target
2669
+ * @param {string} prompt
2670
+ * @returns {Object} // TODO: Define/Improve HtmxHeaderSpecification
2671
+ */
2672
+ function getHeaders(elt, target, prompt) {
2673
+ var headers = {
2674
+ "HX-Request" : "true",
2675
+ "HX-Trigger" : getRawAttribute(elt, "id"),
2676
+ "HX-Trigger-Name" : getRawAttribute(elt, "name"),
2677
+ "HX-Target" : getAttributeValue(target, "id"),
2678
+ "HX-Current-URL" : getDocument().location.href,
2679
+ }
2680
+ getValuesForElement(elt, "hx-headers", false, headers)
2681
+ if (prompt !== undefined) {
2682
+ headers["HX-Prompt"] = prompt;
2683
+ }
2684
+ if (getInternalData(elt).boosted) {
2685
+ headers["HX-Boosted"] = "true";
2686
+ }
2687
+ return headers;
2688
+ }
2689
+
2690
+ /**
2691
+ * filterValues takes an object containing form input values
2692
+ * and returns a new object that only contains keys that are
2693
+ * specified by the closest "hx-params" attribute
2694
+ * @param {Object} inputValues
2695
+ * @param {HTMLElement} elt
2696
+ * @returns {Object}
2697
+ */
2698
+ function filterValues(inputValues, elt) {
2699
+ var paramsValue = getClosestAttributeValue(elt, "hx-params");
2700
+ if (paramsValue) {
2701
+ if (paramsValue === "none") {
2702
+ return {};
2703
+ } else if (paramsValue === "*") {
2704
+ return inputValues;
2705
+ } else if(paramsValue.indexOf("not ") === 0) {
2706
+ forEach(paramsValue.substr(4).split(","), function (name) {
2707
+ name = name.trim();
2708
+ delete inputValues[name];
2709
+ });
2710
+ return inputValues;
2711
+ } else {
2712
+ var newValues = {}
2713
+ forEach(paramsValue.split(","), function (name) {
2714
+ name = name.trim();
2715
+ newValues[name] = inputValues[name];
2716
+ });
2717
+ return newValues;
2718
+ }
2719
+ } else {
2720
+ return inputValues;
2721
+ }
2722
+ }
2723
+
2724
+ function isAnchorLink(elt) {
2725
+ return getRawAttribute(elt, 'href') && getRawAttribute(elt, 'href').indexOf("#") >=0
2726
+ }
2727
+
2728
+ /**
2729
+ *
2730
+ * @param {HTMLElement} elt
2731
+ * @param {string} swapInfoOverride
2732
+ * @returns {import("./htmx").HtmxSwapSpecification}
2733
+ */
2734
+ function getSwapSpecification(elt, swapInfoOverride) {
2735
+ var swapInfo = swapInfoOverride ? swapInfoOverride : getClosestAttributeValue(elt, "hx-swap");
2736
+ var swapSpec = {
2737
+ "swapStyle" : getInternalData(elt).boosted ? 'innerHTML' : htmx.config.defaultSwapStyle,
2738
+ "swapDelay" : htmx.config.defaultSwapDelay,
2739
+ "settleDelay" : htmx.config.defaultSettleDelay
2740
+ }
2741
+ if (htmx.config.scrollIntoViewOnBoost && getInternalData(elt).boosted && !isAnchorLink(elt)) {
2742
+ swapSpec["show"] = "top"
2743
+ }
2744
+ if (swapInfo) {
2745
+ var split = splitOnWhitespace(swapInfo);
2746
+ if (split.length > 0) {
2747
+ for (var i = 0; i < split.length; i++) {
2748
+ var value = split[i];
2749
+ if (value.indexOf("swap:") === 0) {
2750
+ swapSpec["swapDelay"] = parseInterval(value.substr(5));
2751
+ } else if (value.indexOf("settle:") === 0) {
2752
+ swapSpec["settleDelay"] = parseInterval(value.substr(7));
2753
+ } else if (value.indexOf("transition:") === 0) {
2754
+ swapSpec["transition"] = value.substr(11) === "true";
2755
+ } else if (value.indexOf("ignoreTitle:") === 0) {
2756
+ swapSpec["ignoreTitle"] = value.substr(12) === "true";
2757
+ } else if (value.indexOf("scroll:") === 0) {
2758
+ var scrollSpec = value.substr(7);
2759
+ var splitSpec = scrollSpec.split(":");
2760
+ var scrollVal = splitSpec.pop();
2761
+ var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null;
2762
+ swapSpec["scroll"] = scrollVal;
2763
+ swapSpec["scrollTarget"] = selectorVal;
2764
+ } else if (value.indexOf("show:") === 0) {
2765
+ var showSpec = value.substr(5);
2766
+ var splitSpec = showSpec.split(":");
2767
+ var showVal = splitSpec.pop();
2768
+ var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null;
2769
+ swapSpec["show"] = showVal;
2770
+ swapSpec["showTarget"] = selectorVal;
2771
+ } else if (value.indexOf("focus-scroll:") === 0) {
2772
+ var focusScrollVal = value.substr("focus-scroll:".length);
2773
+ swapSpec["focusScroll"] = focusScrollVal == "true";
2774
+ } else if (i == 0) {
2775
+ swapSpec["swapStyle"] = value;
2776
+ } else {
2777
+ logError('Unknown modifier in hx-swap: ' + value);
2778
+ }
2779
+ }
2780
+ }
2781
+ }
2782
+ return swapSpec;
2783
+ }
2784
+
2785
+ function usesFormData(elt) {
2786
+ return getClosestAttributeValue(elt, "hx-encoding") === "multipart/form-data" ||
2787
+ (matches(elt, "form") && getRawAttribute(elt, 'enctype') === "multipart/form-data");
2788
+ }
2789
+
2790
+ function encodeParamsForBody(xhr, elt, filteredParameters) {
2791
+ var encodedParameters = null;
2792
+ withExtensions(elt, function (extension) {
2793
+ if (encodedParameters == null) {
2794
+ encodedParameters = extension.encodeParameters(xhr, filteredParameters, elt);
2795
+ }
2796
+ });
2797
+ if (encodedParameters != null) {
2798
+ return encodedParameters;
2799
+ } else {
2800
+ if (usesFormData(elt)) {
2801
+ return makeFormData(filteredParameters);
2802
+ } else {
2803
+ return urlEncode(filteredParameters);
2804
+ }
2805
+ }
2806
+ }
2807
+
2808
+ /**
2809
+ *
2810
+ * @param {Element} target
2811
+ * @returns {import("./htmx").HtmxSettleInfo}
2812
+ */
2813
+ function makeSettleInfo(target) {
2814
+ return {tasks: [], elts: [target]};
2815
+ }
2816
+
2817
+ function updateScrollState(content, swapSpec) {
2818
+ var first = content[0];
2819
+ var last = content[content.length - 1];
2820
+ if (swapSpec.scroll) {
2821
+ var target = null;
2822
+ if (swapSpec.scrollTarget) {
2823
+ target = querySelectorExt(first, swapSpec.scrollTarget);
2824
+ }
2825
+ if (swapSpec.scroll === "top" && (first || target)) {
2826
+ target = target || first;
2827
+ target.scrollTop = 0;
2828
+ }
2829
+ if (swapSpec.scroll === "bottom" && (last || target)) {
2830
+ target = target || last;
2831
+ target.scrollTop = target.scrollHeight;
2832
+ }
2833
+ }
2834
+ if (swapSpec.show) {
2835
+ var target = null;
2836
+ if (swapSpec.showTarget) {
2837
+ var targetStr = swapSpec.showTarget;
2838
+ if (swapSpec.showTarget === "window") {
2839
+ targetStr = "body";
2840
+ }
2841
+ target = querySelectorExt(first, targetStr);
2842
+ }
2843
+ if (swapSpec.show === "top" && (first || target)) {
2844
+ target = target || first;
2845
+ target.scrollIntoView({block:'start', behavior: htmx.config.scrollBehavior});
2846
+ }
2847
+ if (swapSpec.show === "bottom" && (last || target)) {
2848
+ target = target || last;
2849
+ target.scrollIntoView({block:'end', behavior: htmx.config.scrollBehavior});
2850
+ }
2851
+ }
2852
+ }
2853
+
2854
+ /**
2855
+ * @param {HTMLElement} elt
2856
+ * @param {string} attr
2857
+ * @param {boolean=} evalAsDefault
2858
+ * @param {Object=} values
2859
+ * @returns {Object}
2860
+ */
2861
+ function getValuesForElement(elt, attr, evalAsDefault, values) {
2862
+ if (values == null) {
2863
+ values = {};
2864
+ }
2865
+ if (elt == null) {
2866
+ return values;
2867
+ }
2868
+ var attributeValue = getAttributeValue(elt, attr);
2869
+ if (attributeValue) {
2870
+ var str = attributeValue.trim();
2871
+ var evaluateValue = evalAsDefault;
2872
+ if (str === "unset") {
2873
+ return null;
2874
+ }
2875
+ if (str.indexOf("javascript:") === 0) {
2876
+ str = str.substr(11);
2877
+ evaluateValue = true;
2878
+ } else if (str.indexOf("js:") === 0) {
2879
+ str = str.substr(3);
2880
+ evaluateValue = true;
2881
+ }
2882
+ if (str.indexOf('{') !== 0) {
2883
+ str = "{" + str + "}";
2884
+ }
2885
+ var varsValues;
2886
+ if (evaluateValue) {
2887
+ varsValues = maybeEval(elt,function () {return Function("return (" + str + ")")();}, {});
2888
+ } else {
2889
+ varsValues = parseJSON(str);
2890
+ }
2891
+ for (var key in varsValues) {
2892
+ if (varsValues.hasOwnProperty(key)) {
2893
+ if (values[key] == null) {
2894
+ values[key] = varsValues[key];
2895
+ }
2896
+ }
2897
+ }
2898
+ }
2899
+ return getValuesForElement(parentElt(elt), attr, evalAsDefault, values);
2900
+ }
2901
+
2902
+ function maybeEval(elt, toEval, defaultVal) {
2903
+ if (htmx.config.allowEval) {
2904
+ return toEval();
2905
+ } else {
2906
+ triggerErrorEvent(elt, 'htmx:evalDisallowedError');
2907
+ return defaultVal;
2908
+ }
2909
+ }
2910
+
2911
+ /**
2912
+ * @param {HTMLElement} elt
2913
+ * @param {*} expressionVars
2914
+ * @returns
2915
+ */
2916
+ function getHXVarsForElement(elt, expressionVars) {
2917
+ return getValuesForElement(elt, "hx-vars", true, expressionVars);
2918
+ }
2919
+
2920
+ /**
2921
+ * @param {HTMLElement} elt
2922
+ * @param {*} expressionVars
2923
+ * @returns
2924
+ */
2925
+ function getHXValsForElement(elt, expressionVars) {
2926
+ return getValuesForElement(elt, "hx-vals", false, expressionVars);
2927
+ }
2928
+
2929
+ /**
2930
+ * @param {HTMLElement} elt
2931
+ * @returns {Object}
2932
+ */
2933
+ function getExpressionVars(elt) {
2934
+ return mergeObjects(getHXVarsForElement(elt), getHXValsForElement(elt));
2935
+ }
2936
+
2937
+ function safelySetHeaderValue(xhr, header, headerValue) {
2938
+ if (headerValue !== null) {
2939
+ try {
2940
+ xhr.setRequestHeader(header, headerValue);
2941
+ } catch (e) {
2942
+ // On an exception, try to set the header URI encoded instead
2943
+ xhr.setRequestHeader(header, encodeURIComponent(headerValue));
2944
+ xhr.setRequestHeader(header + "-URI-AutoEncoded", "true");
2945
+ }
2946
+ }
2947
+ }
2948
+
2949
+ function getPathFromResponse(xhr) {
2950
+ // NB: IE11 does not support this stuff
2951
+ if (xhr.responseURL && typeof(URL) !== "undefined") {
2952
+ try {
2953
+ var url = new URL(xhr.responseURL);
2954
+ return url.pathname + url.search;
2955
+ } catch (e) {
2956
+ triggerErrorEvent(getDocument().body, "htmx:badResponseUrl", {url: xhr.responseURL});
2957
+ }
2958
+ }
2959
+ }
2960
+
2961
+ function hasHeader(xhr, regexp) {
2962
+ return regexp.test(xhr.getAllResponseHeaders())
2963
+ }
2964
+
2965
+ function ajaxHelper(verb, path, context) {
2966
+ verb = verb.toLowerCase();
2967
+ if (context) {
2968
+ if (context instanceof Element || isType(context, 'String')) {
2969
+ return issueAjaxRequest(verb, path, null, null, {
2970
+ targetOverride: resolveTarget(context),
2971
+ returnPromise: true
2972
+ });
2973
+ } else {
2974
+ return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event,
2975
+ {
2976
+ handler : context.handler,
2977
+ headers : context.headers,
2978
+ values : context.values,
2979
+ targetOverride: resolveTarget(context.target),
2980
+ swapOverride: context.swap,
2981
+ select: context.select,
2982
+ returnPromise: true
2983
+ });
2984
+ }
2985
+ } else {
2986
+ return issueAjaxRequest(verb, path, null, null, {
2987
+ returnPromise: true
2988
+ });
2989
+ }
2990
+ }
2991
+
2992
+ function hierarchyForElt(elt) {
2993
+ var arr = [];
2994
+ while (elt) {
2995
+ arr.push(elt);
2996
+ elt = elt.parentElement;
2997
+ }
2998
+ return arr;
2999
+ }
3000
+
3001
+ function verifyPath(elt, path, requestConfig) {
3002
+ var sameHost
3003
+ var url
3004
+ if (typeof URL === "function") {
3005
+ url = new URL(path, document.location.href);
3006
+ var origin = document.location.origin;
3007
+ sameHost = origin === url.origin;
3008
+ } else {
3009
+ // IE11 doesn't support URL
3010
+ url = path
3011
+ sameHost = startsWith(path, document.location.origin)
3012
+ }
3013
+
3014
+ if (htmx.config.selfRequestsOnly) {
3015
+ if (!sameHost) {
3016
+ return false;
3017
+ }
3018
+ }
3019
+ return triggerEvent(elt, "htmx:validateUrl", mergeObjects({url: url, sameHost: sameHost}, requestConfig));
3020
+ }
3021
+
3022
+ function issueAjaxRequest(verb, path, elt, event, etc, confirmed) {
3023
+ var resolve = null;
3024
+ var reject = null;
3025
+ etc = etc != null ? etc : {};
3026
+ if(etc.returnPromise && typeof Promise !== "undefined"){
3027
+ var promise = new Promise(function (_resolve, _reject) {
3028
+ resolve = _resolve;
3029
+ reject = _reject;
3030
+ });
3031
+ }
3032
+ if(elt == null) {
3033
+ elt = getDocument().body;
3034
+ }
3035
+ var responseHandler = etc.handler || handleAjaxResponse;
3036
+ var select = etc.select || null;
3037
+
3038
+ if (!bodyContains(elt)) {
3039
+ // do not issue requests for elements removed from the DOM
3040
+ maybeCall(resolve);
3041
+ return promise;
3042
+ }
3043
+ var target = etc.targetOverride || getTarget(elt);
3044
+ if (target == null || target == DUMMY_ELT) {
3045
+ triggerErrorEvent(elt, 'htmx:targetError', {target: getAttributeValue(elt, "hx-target")});
3046
+ maybeCall(reject);
3047
+ return promise;
3048
+ }
3049
+
3050
+ var eltData = getInternalData(elt);
3051
+ var submitter = eltData.lastButtonClicked;
3052
+
3053
+ if (submitter) {
3054
+ var buttonPath = getRawAttribute(submitter, "formaction");
3055
+ if (buttonPath != null) {
3056
+ path = buttonPath;
3057
+ }
3058
+
3059
+ var buttonVerb = getRawAttribute(submitter, "formmethod")
3060
+ if (buttonVerb != null) {
3061
+ // ignore buttons with formmethod="dialog"
3062
+ if (buttonVerb.toLowerCase() !== "dialog") {
3063
+ verb = buttonVerb;
3064
+ }
3065
+ }
3066
+ }
3067
+
3068
+ var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm");
3069
+ // allow event-based confirmation w/ a callback
3070
+ if (confirmed === undefined) {
3071
+ var issueRequest = function(skipConfirmation) {
3072
+ return issueAjaxRequest(verb, path, elt, event, etc, !!skipConfirmation);
3073
+ }
3074
+ var confirmDetails = {target: target, elt: elt, path: path, verb: verb, triggeringEvent: event, etc: etc, issueRequest: issueRequest, question: confirmQuestion};
3075
+ if (triggerEvent(elt, 'htmx:confirm', confirmDetails) === false) {
3076
+ maybeCall(resolve);
3077
+ return promise;
3078
+ }
3079
+ }
3080
+
3081
+ var syncElt = elt;
3082
+ var syncStrategy = getClosestAttributeValue(elt, "hx-sync");
3083
+ var queueStrategy = null;
3084
+ var abortable = false;
3085
+ if (syncStrategy) {
3086
+ var syncStrings = syncStrategy.split(":");
3087
+ var selector = syncStrings[0].trim();
3088
+ if (selector === "this") {
3089
+ syncElt = findThisElement(elt, 'hx-sync');
3090
+ } else {
3091
+ syncElt = querySelectorExt(elt, selector);
3092
+ }
3093
+ // default to the drop strategy
3094
+ syncStrategy = (syncStrings[1] || 'drop').trim();
3095
+ eltData = getInternalData(syncElt);
3096
+ if (syncStrategy === "drop" && eltData.xhr && eltData.abortable !== true) {
3097
+ maybeCall(resolve);
3098
+ return promise;
3099
+ } else if (syncStrategy === "abort") {
3100
+ if (eltData.xhr) {
3101
+ maybeCall(resolve);
3102
+ return promise;
3103
+ } else {
3104
+ abortable = true;
3105
+ }
3106
+ } else if (syncStrategy === "replace") {
3107
+ triggerEvent(syncElt, 'htmx:abort'); // abort the current request and continue
3108
+ } else if (syncStrategy.indexOf("queue") === 0) {
3109
+ var queueStrArray = syncStrategy.split(" ");
3110
+ queueStrategy = (queueStrArray[1] || "last").trim();
3111
+ }
3112
+ }
3113
+
3114
+ if (eltData.xhr) {
3115
+ if (eltData.abortable) {
3116
+ triggerEvent(syncElt, 'htmx:abort'); // abort the current request and continue
3117
+ } else {
3118
+ if(queueStrategy == null){
3119
+ if (event) {
3120
+ var eventData = getInternalData(event);
3121
+ if (eventData && eventData.triggerSpec && eventData.triggerSpec.queue) {
3122
+ queueStrategy = eventData.triggerSpec.queue;
3123
+ }
3124
+ }
3125
+ if (queueStrategy == null) {
3126
+ queueStrategy = "last";
3127
+ }
3128
+ }
3129
+ if (eltData.queuedRequests == null) {
3130
+ eltData.queuedRequests = [];
3131
+ }
3132
+ if (queueStrategy === "first" && eltData.queuedRequests.length === 0) {
3133
+ eltData.queuedRequests.push(function () {
3134
+ issueAjaxRequest(verb, path, elt, event, etc)
3135
+ });
3136
+ } else if (queueStrategy === "all") {
3137
+ eltData.queuedRequests.push(function () {
3138
+ issueAjaxRequest(verb, path, elt, event, etc)
3139
+ });
3140
+ } else if (queueStrategy === "last") {
3141
+ eltData.queuedRequests = []; // dump existing queue
3142
+ eltData.queuedRequests.push(function () {
3143
+ issueAjaxRequest(verb, path, elt, event, etc)
3144
+ });
3145
+ }
3146
+ maybeCall(resolve);
3147
+ return promise;
3148
+ }
3149
+ }
3150
+
3151
+ var xhr = new XMLHttpRequest();
3152
+ eltData.xhr = xhr;
3153
+ eltData.abortable = abortable;
3154
+ var endRequestLock = function(){
3155
+ eltData.xhr = null;
3156
+ eltData.abortable = false;
3157
+ if (eltData.queuedRequests != null &&
3158
+ eltData.queuedRequests.length > 0) {
3159
+ var queuedRequest = eltData.queuedRequests.shift();
3160
+ queuedRequest();
3161
+ }
3162
+ }
3163
+ var promptQuestion = getClosestAttributeValue(elt, "hx-prompt");
3164
+ if (promptQuestion) {
3165
+ var promptResponse = prompt(promptQuestion);
3166
+ // prompt returns null if cancelled and empty string if accepted with no entry
3167
+ if (promptResponse === null ||
3168
+ !triggerEvent(elt, 'htmx:prompt', {prompt: promptResponse, target:target})) {
3169
+ maybeCall(resolve);
3170
+ endRequestLock();
3171
+ return promise;
3172
+ }
3173
+ }
3174
+
3175
+ if (confirmQuestion && !confirmed) {
3176
+ if(!confirm(confirmQuestion)) {
3177
+ maybeCall(resolve);
3178
+ endRequestLock()
3179
+ return promise;
3180
+ }
3181
+ }
3182
+
3183
+
3184
+ var headers = getHeaders(elt, target, promptResponse);
3185
+
3186
+ if (verb !== 'get' && !usesFormData(elt)) {
3187
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
3188
+ }
3189
+
3190
+ if (etc.headers) {
3191
+ headers = mergeObjects(headers, etc.headers);
3192
+ }
3193
+ var results = getInputValues(elt, verb);
3194
+ var errors = results.errors;
3195
+ var rawParameters = results.values;
3196
+ if (etc.values) {
3197
+ rawParameters = mergeObjects(rawParameters, etc.values);
3198
+ }
3199
+ var expressionVars = getExpressionVars(elt);
3200
+ var allParameters = mergeObjects(rawParameters, expressionVars);
3201
+ var filteredParameters = filterValues(allParameters, elt);
3202
+
3203
+ if (htmx.config.getCacheBusterParam && verb === 'get') {
3204
+ filteredParameters['org.htmx.cache-buster'] = getRawAttribute(target, "id") || "true";
3205
+ }
3206
+
3207
+ // behavior of anchors w/ empty href is to use the current URL
3208
+ if (path == null || path === "") {
3209
+ path = getDocument().location.href;
3210
+ }
3211
+
3212
+
3213
+ var requestAttrValues = getValuesForElement(elt, 'hx-request');
3214
+
3215
+ var eltIsBoosted = getInternalData(elt).boosted;
3216
+
3217
+ var useUrlParams = htmx.config.methodsThatUseUrlParams.indexOf(verb) >= 0
3218
+
3219
+ var requestConfig = {
3220
+ boosted: eltIsBoosted,
3221
+ useUrlParams: useUrlParams,
3222
+ parameters: filteredParameters,
3223
+ unfilteredParameters: allParameters,
3224
+ headers:headers,
3225
+ target:target,
3226
+ verb:verb,
3227
+ errors:errors,
3228
+ withCredentials: etc.credentials || requestAttrValues.credentials || htmx.config.withCredentials,
3229
+ timeout: etc.timeout || requestAttrValues.timeout || htmx.config.timeout,
3230
+ path:path,
3231
+ triggeringEvent:event
3232
+ };
3233
+
3234
+ if(!triggerEvent(elt, 'htmx:configRequest', requestConfig)){
3235
+ maybeCall(resolve);
3236
+ endRequestLock();
3237
+ return promise;
3238
+ }
3239
+
3240
+ // copy out in case the object was overwritten
3241
+ path = requestConfig.path;
3242
+ verb = requestConfig.verb;
3243
+ headers = requestConfig.headers;
3244
+ filteredParameters = requestConfig.parameters;
3245
+ errors = requestConfig.errors;
3246
+ useUrlParams = requestConfig.useUrlParams;
3247
+
3248
+ if(errors && errors.length > 0){
3249
+ triggerEvent(elt, 'htmx:validation:halted', requestConfig)
3250
+ maybeCall(resolve);
3251
+ endRequestLock();
3252
+ return promise;
3253
+ }
3254
+
3255
+ var splitPath = path.split("#");
3256
+ var pathNoAnchor = splitPath[0];
3257
+ var anchor = splitPath[1];
3258
+
3259
+ var finalPath = path
3260
+ if (useUrlParams) {
3261
+ finalPath = pathNoAnchor;
3262
+ var values = Object.keys(filteredParameters).length !== 0;
3263
+ if (values) {
3264
+ if (finalPath.indexOf("?") < 0) {
3265
+ finalPath += "?";
3266
+ } else {
3267
+ finalPath += "&";
3268
+ }
3269
+ finalPath += urlEncode(filteredParameters);
3270
+ if (anchor) {
3271
+ finalPath += "#" + anchor;
3272
+ }
3273
+ }
3274
+ }
3275
+
3276
+ if (!verifyPath(elt, finalPath, requestConfig)) {
3277
+ triggerErrorEvent(elt, 'htmx:invalidPath', requestConfig)
3278
+ maybeCall(reject);
3279
+ return promise;
3280
+ };
3281
+
3282
+ xhr.open(verb.toUpperCase(), finalPath, true);
3283
+ xhr.overrideMimeType("text/html");
3284
+ xhr.withCredentials = requestConfig.withCredentials;
3285
+ xhr.timeout = requestConfig.timeout;
3286
+
3287
+ // request headers
3288
+ if (requestAttrValues.noHeaders) {
3289
+ // ignore all headers
3290
+ } else {
3291
+ for (var header in headers) {
3292
+ if (headers.hasOwnProperty(header)) {
3293
+ var headerValue = headers[header];
3294
+ safelySetHeaderValue(xhr, header, headerValue);
3295
+ }
3296
+ }
3297
+ }
3298
+
3299
+ var responseInfo = {
3300
+ xhr: xhr, target: target, requestConfig: requestConfig, etc: etc, boosted: eltIsBoosted, select: select,
3301
+ pathInfo: {
3302
+ requestPath: path,
3303
+ finalRequestPath: finalPath,
3304
+ anchor: anchor
3305
+ }
3306
+ };
3307
+
3308
+ xhr.onload = function () {
3309
+ try {
3310
+ var hierarchy = hierarchyForElt(elt);
3311
+ responseInfo.pathInfo.responsePath = getPathFromResponse(xhr);
3312
+ responseHandler(elt, responseInfo);
3313
+ removeRequestIndicators(indicators, disableElts);
3314
+ triggerEvent(elt, 'htmx:afterRequest', responseInfo);
3315
+ triggerEvent(elt, 'htmx:afterOnLoad', responseInfo);
3316
+ // if the body no longer contains the element, trigger the event on the closest parent
3317
+ // remaining in the DOM
3318
+ if (!bodyContains(elt)) {
3319
+ var secondaryTriggerElt = null;
3320
+ while (hierarchy.length > 0 && secondaryTriggerElt == null) {
3321
+ var parentEltInHierarchy = hierarchy.shift();
3322
+ if (bodyContains(parentEltInHierarchy)) {
3323
+ secondaryTriggerElt = parentEltInHierarchy;
3324
+ }
3325
+ }
3326
+ if (secondaryTriggerElt) {
3327
+ triggerEvent(secondaryTriggerElt, 'htmx:afterRequest', responseInfo);
3328
+ triggerEvent(secondaryTriggerElt, 'htmx:afterOnLoad', responseInfo);
3329
+ }
3330
+ }
3331
+ maybeCall(resolve);
3332
+ endRequestLock();
3333
+ } catch (e) {
3334
+ triggerErrorEvent(elt, 'htmx:onLoadError', mergeObjects({error:e}, responseInfo));
3335
+ throw e;
3336
+ }
3337
+ }
3338
+ xhr.onerror = function () {
3339
+ removeRequestIndicators(indicators, disableElts);
3340
+ triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
3341
+ triggerErrorEvent(elt, 'htmx:sendError', responseInfo);
3342
+ maybeCall(reject);
3343
+ endRequestLock();
3344
+ }
3345
+ xhr.onabort = function() {
3346
+ removeRequestIndicators(indicators, disableElts);
3347
+ triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
3348
+ triggerErrorEvent(elt, 'htmx:sendAbort', responseInfo);
3349
+ maybeCall(reject);
3350
+ endRequestLock();
3351
+ }
3352
+ xhr.ontimeout = function() {
3353
+ removeRequestIndicators(indicators, disableElts);
3354
+ triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
3355
+ triggerErrorEvent(elt, 'htmx:timeout', responseInfo);
3356
+ maybeCall(reject);
3357
+ endRequestLock();
3358
+ }
3359
+ if(!triggerEvent(elt, 'htmx:beforeRequest', responseInfo)){
3360
+ maybeCall(resolve);
3361
+ endRequestLock()
3362
+ return promise
3363
+ }
3364
+ var indicators = addRequestIndicatorClasses(elt);
3365
+ var disableElts = disableElements(elt);
3366
+
3367
+ forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) {
3368
+ forEach([xhr, xhr.upload], function (target) {
3369
+ target.addEventListener(eventName, function(event){
3370
+ triggerEvent(elt, "htmx:xhr:" + eventName, {
3371
+ lengthComputable:event.lengthComputable,
3372
+ loaded:event.loaded,
3373
+ total:event.total
3374
+ });
3375
+ })
3376
+ });
3377
+ });
3378
+ triggerEvent(elt, 'htmx:beforeSend', responseInfo);
3379
+ var params = useUrlParams ? null : encodeParamsForBody(xhr, elt, filteredParameters)
3380
+ xhr.send(params);
3381
+ return promise;
3382
+ }
3383
+
3384
+ function determineHistoryUpdates(elt, responseInfo) {
3385
+
3386
+ var xhr = responseInfo.xhr;
3387
+
3388
+ //===========================================
3389
+ // First consult response headers
3390
+ //===========================================
3391
+ var pathFromHeaders = null;
3392
+ var typeFromHeaders = null;
3393
+ if (hasHeader(xhr,/HX-Push:/i)) {
3394
+ pathFromHeaders = xhr.getResponseHeader("HX-Push");
3395
+ typeFromHeaders = "push";
3396
+ } else if (hasHeader(xhr,/HX-Push-Url:/i)) {
3397
+ pathFromHeaders = xhr.getResponseHeader("HX-Push-Url");
3398
+ typeFromHeaders = "push";
3399
+ } else if (hasHeader(xhr,/HX-Replace-Url:/i)) {
3400
+ pathFromHeaders = xhr.getResponseHeader("HX-Replace-Url");
3401
+ typeFromHeaders = "replace";
3402
+ }
3403
+
3404
+ // if there was a response header, that has priority
3405
+ if (pathFromHeaders) {
3406
+ if (pathFromHeaders === "false") {
3407
+ return {}
3408
+ } else {
3409
+ return {
3410
+ type: typeFromHeaders,
3411
+ path : pathFromHeaders
3412
+ }
3413
+ }
3414
+ }
3415
+
3416
+ //===========================================
3417
+ // Next resolve via DOM values
3418
+ //===========================================
3419
+ var requestPath = responseInfo.pathInfo.finalRequestPath;
3420
+ var responsePath = responseInfo.pathInfo.responsePath;
3421
+
3422
+ var pushUrl = getClosestAttributeValue(elt, "hx-push-url");
3423
+ var replaceUrl = getClosestAttributeValue(elt, "hx-replace-url");
3424
+ var elementIsBoosted = getInternalData(elt).boosted;
3425
+
3426
+ var saveType = null;
3427
+ var path = null;
3428
+
3429
+ if (pushUrl) {
3430
+ saveType = "push";
3431
+ path = pushUrl;
3432
+ } else if (replaceUrl) {
3433
+ saveType = "replace";
3434
+ path = replaceUrl;
3435
+ } else if (elementIsBoosted) {
3436
+ saveType = "push";
3437
+ path = responsePath || requestPath; // if there is no response path, go with the original request path
3438
+ }
3439
+
3440
+ if (path) {
3441
+ // false indicates no push, return empty object
3442
+ if (path === "false") {
3443
+ return {};
3444
+ }
3445
+
3446
+ // true indicates we want to follow wherever the server ended up sending us
3447
+ if (path === "true") {
3448
+ path = responsePath || requestPath; // if there is no response path, go with the original request path
3449
+ }
3450
+
3451
+ // restore any anchor associated with the request
3452
+ if (responseInfo.pathInfo.anchor &&
3453
+ path.indexOf("#") === -1) {
3454
+ path = path + "#" + responseInfo.pathInfo.anchor;
3455
+ }
3456
+
3457
+ return {
3458
+ type:saveType,
3459
+ path: path
3460
+ }
3461
+ } else {
3462
+ return {};
3463
+ }
3464
+ }
3465
+
3466
+ function handleAjaxResponse(elt, responseInfo) {
3467
+ var xhr = responseInfo.xhr;
3468
+ var target = responseInfo.target;
3469
+ var etc = responseInfo.etc;
3470
+ var requestConfig = responseInfo.requestConfig;
3471
+ var select = responseInfo.select;
3472
+
3473
+ if (!triggerEvent(elt, 'htmx:beforeOnLoad', responseInfo)) return;
3474
+
3475
+ if (hasHeader(xhr, /HX-Trigger:/i)) {
3476
+ handleTrigger(xhr, "HX-Trigger", elt);
3477
+ }
3478
+
3479
+ if (hasHeader(xhr, /HX-Location:/i)) {
3480
+ saveCurrentPageToHistory();
3481
+ var redirectPath = xhr.getResponseHeader("HX-Location");
3482
+ var swapSpec;
3483
+ if (redirectPath.indexOf("{") === 0) {
3484
+ swapSpec = parseJSON(redirectPath);
3485
+ // what's the best way to throw an error if the user didn't include this
3486
+ redirectPath = swapSpec['path'];
3487
+ delete swapSpec['path'];
3488
+ }
3489
+ ajaxHelper('GET', redirectPath, swapSpec).then(function(){
3490
+ pushUrlIntoHistory(redirectPath);
3491
+ });
3492
+ return;
3493
+ }
3494
+
3495
+ var shouldRefresh = hasHeader(xhr, /HX-Refresh:/i) && "true" === xhr.getResponseHeader("HX-Refresh");
3496
+
3497
+ if (hasHeader(xhr, /HX-Redirect:/i)) {
3498
+ location.href = xhr.getResponseHeader("HX-Redirect");
3499
+ shouldRefresh && location.reload();
3500
+ return;
3501
+ }
3502
+
3503
+ if (shouldRefresh) {
3504
+ location.reload();
3505
+ return;
3506
+ }
3507
+
3508
+ if (hasHeader(xhr,/HX-Retarget:/i)) {
3509
+ if (xhr.getResponseHeader("HX-Retarget") === "this") {
3510
+ responseInfo.target = elt;
3511
+ } else {
3512
+ responseInfo.target = querySelectorExt(elt, xhr.getResponseHeader("HX-Retarget"));
3513
+ }
3514
+ }
3515
+
3516
+ var historyUpdate = determineHistoryUpdates(elt, responseInfo);
3517
+
3518
+ // by default htmx only swaps on 200 return codes and does not swap
3519
+ // on 204 'No Content'
3520
+ // this can be ovverriden by responding to the htmx:beforeSwap event and
3521
+ // overriding the detail.shouldSwap property
3522
+ var shouldSwap = xhr.status >= 200 && xhr.status < 400 && xhr.status !== 204;
3523
+ var serverResponse = xhr.response;
3524
+ var isError = xhr.status >= 400;
3525
+ var ignoreTitle = htmx.config.ignoreTitle
3526
+ var beforeSwapDetails = mergeObjects({shouldSwap: shouldSwap, serverResponse:serverResponse, isError:isError, ignoreTitle:ignoreTitle }, responseInfo);
3527
+ if (!triggerEvent(target, 'htmx:beforeSwap', beforeSwapDetails)) return;
3528
+
3529
+ target = beforeSwapDetails.target; // allow re-targeting
3530
+ serverResponse = beforeSwapDetails.serverResponse; // allow updating content
3531
+ isError = beforeSwapDetails.isError; // allow updating error
3532
+ ignoreTitle = beforeSwapDetails.ignoreTitle; // allow updating ignoring title
3533
+
3534
+ responseInfo.target = target; // Make updated target available to response events
3535
+ responseInfo.failed = isError; // Make failed property available to response events
3536
+ responseInfo.successful = !isError; // Make successful property available to response events
3537
+
3538
+ if (beforeSwapDetails.shouldSwap) {
3539
+ if (xhr.status === 286) {
3540
+ cancelPolling(elt);
3541
+ }
3542
+
3543
+ withExtensions(elt, function (extension) {
3544
+ serverResponse = extension.transformResponse(serverResponse, xhr, elt);
3545
+ });
3546
+
3547
+ // Save current page if there will be a history update
3548
+ if (historyUpdate.type) {
3549
+ saveCurrentPageToHistory();
3550
+ }
3551
+
3552
+ var swapOverride = etc.swapOverride;
3553
+ if (hasHeader(xhr,/HX-Reswap:/i)) {
3554
+ swapOverride = xhr.getResponseHeader("HX-Reswap");
3555
+ }
3556
+ var swapSpec = getSwapSpecification(elt, swapOverride);
3557
+
3558
+ if (swapSpec.hasOwnProperty('ignoreTitle')) {
3559
+ ignoreTitle = swapSpec.ignoreTitle;
3560
+ }
3561
+
3562
+ target.classList.add(htmx.config.swappingClass);
3563
+
3564
+ // optional transition API promise callbacks
3565
+ var settleResolve = null;
3566
+ var settleReject = null;
3567
+
3568
+ var doSwap = function () {
3569
+ try {
3570
+ var activeElt = document.activeElement;
3571
+ var selectionInfo = {};
3572
+ try {
3573
+ selectionInfo = {
3574
+ elt: activeElt,
3575
+ // @ts-ignore
3576
+ start: activeElt ? activeElt.selectionStart : null,
3577
+ // @ts-ignore
3578
+ end: activeElt ? activeElt.selectionEnd : null
3579
+ };
3580
+ } catch (e) {
3581
+ // safari issue - see https://github.com/microsoft/playwright/issues/5894
3582
+ }
3583
+
3584
+ var selectOverride;
3585
+ if (select) {
3586
+ selectOverride = select;
3587
+ }
3588
+
3589
+ if (hasHeader(xhr, /HX-Reselect:/i)) {
3590
+ selectOverride = xhr.getResponseHeader("HX-Reselect");
3591
+ }
3592
+
3593
+ // if we need to save history, do so, before swapping so that relative resources have the correct base URL
3594
+ if (historyUpdate.type) {
3595
+ triggerEvent(getDocument().body, 'htmx:beforeHistoryUpdate', mergeObjects({ history: historyUpdate }, responseInfo));
3596
+ if (historyUpdate.type === "push") {
3597
+ pushUrlIntoHistory(historyUpdate.path);
3598
+ triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', {path: historyUpdate.path});
3599
+ } else {
3600
+ replaceUrlInHistory(historyUpdate.path);
3601
+ triggerEvent(getDocument().body, 'htmx:replacedInHistory', {path: historyUpdate.path});
3602
+ }
3603
+ }
3604
+
3605
+ var settleInfo = makeSettleInfo(target);
3606
+ selectAndSwap(swapSpec.swapStyle, target, elt, serverResponse, settleInfo, selectOverride);
3607
+
3608
+ if (selectionInfo.elt &&
3609
+ !bodyContains(selectionInfo.elt) &&
3610
+ getRawAttribute(selectionInfo.elt, "id")) {
3611
+ var newActiveElt = document.getElementById(getRawAttribute(selectionInfo.elt, "id"));
3612
+ var focusOptions = { preventScroll: swapSpec.focusScroll !== undefined ? !swapSpec.focusScroll : !htmx.config.defaultFocusScroll };
3613
+ if (newActiveElt) {
3614
+ // @ts-ignore
3615
+ if (selectionInfo.start && newActiveElt.setSelectionRange) {
3616
+ // @ts-ignore
3617
+ try {
3618
+ newActiveElt.setSelectionRange(selectionInfo.start, selectionInfo.end);
3619
+ } catch (e) {
3620
+ // the setSelectionRange method is present on fields that don't support it, so just let this fail
3621
+ }
3622
+ }
3623
+ newActiveElt.focus(focusOptions);
3624
+ }
3625
+ }
3626
+
3627
+ target.classList.remove(htmx.config.swappingClass);
3628
+ forEach(settleInfo.elts, function (elt) {
3629
+ if (elt.classList) {
3630
+ elt.classList.add(htmx.config.settlingClass);
3631
+ }
3632
+ triggerEvent(elt, 'htmx:afterSwap', responseInfo);
3633
+ });
3634
+
3635
+ if (hasHeader(xhr, /HX-Trigger-After-Swap:/i)) {
3636
+ var finalElt = elt;
3637
+ if (!bodyContains(elt)) {
3638
+ finalElt = getDocument().body;
3639
+ }
3640
+ handleTrigger(xhr, "HX-Trigger-After-Swap", finalElt);
3641
+ }
3642
+
3643
+ var doSettle = function () {
3644
+ forEach(settleInfo.tasks, function (task) {
3645
+ task.call();
3646
+ });
3647
+ forEach(settleInfo.elts, function (elt) {
3648
+ if (elt.classList) {
3649
+ elt.classList.remove(htmx.config.settlingClass);
3650
+ }
3651
+ triggerEvent(elt, 'htmx:afterSettle', responseInfo);
3652
+ });
3653
+
3654
+ if (responseInfo.pathInfo.anchor) {
3655
+ var anchorTarget = getDocument().getElementById(responseInfo.pathInfo.anchor);
3656
+ if(anchorTarget) {
3657
+ anchorTarget.scrollIntoView({block:'start', behavior: "auto"});
3658
+ }
3659
+ }
3660
+
3661
+ if(settleInfo.title && !ignoreTitle) {
3662
+ var titleElt = find("title");
3663
+ if(titleElt) {
3664
+ titleElt.innerHTML = settleInfo.title;
3665
+ } else {
3666
+ window.document.title = settleInfo.title;
3667
+ }
3668
+ }
3669
+
3670
+ updateScrollState(settleInfo.elts, swapSpec);
3671
+
3672
+ if (hasHeader(xhr, /HX-Trigger-After-Settle:/i)) {
3673
+ var finalElt = elt;
3674
+ if (!bodyContains(elt)) {
3675
+ finalElt = getDocument().body;
3676
+ }
3677
+ handleTrigger(xhr, "HX-Trigger-After-Settle", finalElt);
3678
+ }
3679
+ maybeCall(settleResolve);
3680
+ }
3681
+
3682
+ if (swapSpec.settleDelay > 0) {
3683
+ setTimeout(doSettle, swapSpec.settleDelay)
3684
+ } else {
3685
+ doSettle();
3686
+ }
3687
+ } catch (e) {
3688
+ triggerErrorEvent(elt, 'htmx:swapError', responseInfo);
3689
+ maybeCall(settleReject);
3690
+ throw e;
3691
+ }
3692
+ };
3693
+
3694
+ var shouldTransition = htmx.config.globalViewTransitions
3695
+ if(swapSpec.hasOwnProperty('transition')){
3696
+ shouldTransition = swapSpec.transition;
3697
+ }
3698
+
3699
+ if(shouldTransition &&
3700
+ triggerEvent(elt, 'htmx:beforeTransition', responseInfo) &&
3701
+ typeof Promise !== "undefined" && document.startViewTransition){
3702
+ var settlePromise = new Promise(function (_resolve, _reject) {
3703
+ settleResolve = _resolve;
3704
+ settleReject = _reject;
3705
+ });
3706
+ // wrap the original doSwap() in a call to startViewTransition()
3707
+ var innerDoSwap = doSwap;
3708
+ doSwap = function() {
3709
+ document.startViewTransition(function () {
3710
+ innerDoSwap();
3711
+ return settlePromise;
3712
+ });
3713
+ }
3714
+ }
3715
+
3716
+
3717
+ if (swapSpec.swapDelay > 0) {
3718
+ setTimeout(doSwap, swapSpec.swapDelay)
3719
+ } else {
3720
+ doSwap();
3721
+ }
3722
+ }
3723
+ if (isError) {
3724
+ triggerErrorEvent(elt, 'htmx:responseError', mergeObjects({error: "Response Status Error Code " + xhr.status + " from " + responseInfo.pathInfo.requestPath}, responseInfo));
3725
+ }
3726
+ }
3727
+
3728
+ //====================================================================
3729
+ // Extensions API
3730
+ //====================================================================
3731
+
3732
+ /** @type {Object<string, import("./htmx").HtmxExtension>} */
3733
+ var extensions = {};
3734
+
3735
+ /**
3736
+ * extensionBase defines the default functions for all extensions.
3737
+ * @returns {import("./htmx").HtmxExtension}
3738
+ */
3739
+ function extensionBase() {
3740
+ return {
3741
+ init: function(api) {return null;},
3742
+ onEvent : function(name, evt) {return true;},
3743
+ transformResponse : function(text, xhr, elt) {return text;},
3744
+ isInlineSwap : function(swapStyle) {return false;},
3745
+ handleSwap : function(swapStyle, target, fragment, settleInfo) {return false;},
3746
+ encodeParameters : function(xhr, parameters, elt) {return null;}
3747
+ }
3748
+ }
3749
+
3750
+ /**
3751
+ * defineExtension initializes the extension and adds it to the htmx registry
3752
+ *
3753
+ * @param {string} name
3754
+ * @param {import("./htmx").HtmxExtension} extension
3755
+ */
3756
+ function defineExtension(name, extension) {
3757
+ if(extension.init) {
3758
+ extension.init(internalAPI)
3759
+ }
3760
+ extensions[name] = mergeObjects(extensionBase(), extension);
3761
+ }
3762
+
3763
+ /**
3764
+ * removeExtension removes an extension from the htmx registry
3765
+ *
3766
+ * @param {string} name
3767
+ */
3768
+ function removeExtension(name) {
3769
+ delete extensions[name];
3770
+ }
3771
+
3772
+ /**
3773
+ * getExtensions searches up the DOM tree to return all extensions that can be applied to a given element
3774
+ *
3775
+ * @param {HTMLElement} elt
3776
+ * @param {import("./htmx").HtmxExtension[]=} extensionsToReturn
3777
+ * @param {import("./htmx").HtmxExtension[]=} extensionsToIgnore
3778
+ */
3779
+ function getExtensions(elt, extensionsToReturn, extensionsToIgnore) {
3780
+
3781
+ if (elt == undefined) {
3782
+ return extensionsToReturn;
3783
+ }
3784
+ if (extensionsToReturn == undefined) {
3785
+ extensionsToReturn = [];
3786
+ }
3787
+ if (extensionsToIgnore == undefined) {
3788
+ extensionsToIgnore = [];
3789
+ }
3790
+ var extensionsForElement = getAttributeValue(elt, "hx-ext");
3791
+ if (extensionsForElement) {
3792
+ forEach(extensionsForElement.split(","), function(extensionName){
3793
+ extensionName = extensionName.replace(/ /g, '');
3794
+ if (extensionName.slice(0, 7) == "ignore:") {
3795
+ extensionsToIgnore.push(extensionName.slice(7));
3796
+ return;
3797
+ }
3798
+ if (extensionsToIgnore.indexOf(extensionName) < 0) {
3799
+ var extension = extensions[extensionName];
3800
+ if (extension && extensionsToReturn.indexOf(extension) < 0) {
3801
+ extensionsToReturn.push(extension);
3802
+ }
3803
+ }
3804
+ });
3805
+ }
3806
+ return getExtensions(parentElt(elt), extensionsToReturn, extensionsToIgnore);
3807
+ }
3808
+
3809
+ //====================================================================
3810
+ // Initialization
3811
+ //====================================================================
3812
+ var isReady = false
3813
+ getDocument().addEventListener('DOMContentLoaded', function() {
3814
+ isReady = true
3815
+ })
3816
+
3817
+ /**
3818
+ * Execute a function now if DOMContentLoaded has fired, otherwise listen for it.
3819
+ *
3820
+ * This function uses isReady because there is no realiable way to ask the browswer whether
3821
+ * the DOMContentLoaded event has already been fired; there's a gap between DOMContentLoaded
3822
+ * firing and readystate=complete.
3823
+ */
3824
+ function ready(fn) {
3825
+ // Checking readyState here is a failsafe in case the htmx script tag entered the DOM by
3826
+ // some means other than the initial page load.
3827
+ if (isReady || getDocument().readyState === 'complete') {
3828
+ fn();
3829
+ } else {
3830
+ getDocument().addEventListener('DOMContentLoaded', fn);
3831
+ }
3832
+ }
3833
+
3834
+ function insertIndicatorStyles() {
3835
+ if (htmx.config.includeIndicatorStyles !== false) {
3836
+ getDocument().head.insertAdjacentHTML("beforeend",
3837
+ "<style>\
3838
+ ." + htmx.config.indicatorClass + "{opacity:0}\
3839
+ ." + htmx.config.requestClass + " ." + htmx.config.indicatorClass + "{opacity:1; transition: opacity 200ms ease-in;}\
3840
+ ." + htmx.config.requestClass + "." + htmx.config.indicatorClass + "{opacity:1; transition: opacity 200ms ease-in;}\
3841
+ </style>");
3842
+ }
3843
+ }
3844
+
3845
+ function getMetaConfig() {
3846
+ var element = getDocument().querySelector('meta[name="htmx-config"]');
3847
+ if (element) {
3848
+ // @ts-ignore
3849
+ return parseJSON(element.content);
3850
+ } else {
3851
+ return null;
3852
+ }
3853
+ }
3854
+
3855
+ function mergeMetaConfig() {
3856
+ var metaConfig = getMetaConfig();
3857
+ if (metaConfig) {
3858
+ htmx.config = mergeObjects(htmx.config , metaConfig)
3859
+ }
3860
+ }
3861
+
3862
+ // initialize the document
3863
+ ready(function () {
3864
+ mergeMetaConfig();
3865
+ insertIndicatorStyles();
3866
+ var body = getDocument().body;
3867
+ processNode(body);
3868
+ var restoredElts = getDocument().querySelectorAll(
3869
+ "[hx-trigger='restored'],[data-hx-trigger='restored']"
3870
+ );
3871
+ body.addEventListener("htmx:abort", function (evt) {
3872
+ var target = evt.target;
3873
+ var internalData = getInternalData(target);
3874
+ if (internalData && internalData.xhr) {
3875
+ internalData.xhr.abort();
3876
+ }
3877
+ });
3878
+ /** @type {(ev: PopStateEvent) => any} */
3879
+ const originalPopstate = window.onpopstate ? window.onpopstate.bind(window) : null;
3880
+ /** @type {(ev: PopStateEvent) => any} */
3881
+ window.onpopstate = function (event) {
3882
+ if (event.state && event.state.htmx) {
3883
+ restoreHistory();
3884
+ forEach(restoredElts, function(elt){
3885
+ triggerEvent(elt, 'htmx:restored', {
3886
+ 'document': getDocument(),
3887
+ 'triggerEvent': triggerEvent
3888
+ });
3889
+ });
3890
+ } else {
3891
+ if (originalPopstate) {
3892
+ originalPopstate(event);
3893
+ }
3894
+ }
3895
+ };
3896
+ setTimeout(function () {
3897
+ triggerEvent(body, 'htmx:load', {}); // give ready handlers a chance to load up before firing this event
3898
+ body = null; // kill reference for gc
3899
+ }, 0);
3900
+ })
3901
+
3902
+ return htmx;
3903
+ }
3904
+ )()
3905
+ }));