Browse code

Initial htmx npm packages installation

Benjamin Roth authored on25/05/2023 09:52:13
Showing26 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,281 @@
1
+{
2
+  "name": "contao-htmx",
3
+  "version": "1.0.0",
4
+  "lockfileVersion": 3,
5
+  "requires": true,
6
+  "packages": {
7
+    "": {
8
+      "name": "contao-htmx",
9
+      "version": "1.0.0",
10
+      "hasInstallScript": true,
11
+      "dependencies": {
12
+        "gently-copy": "^3.2.0",
13
+        "htmx.org": "^1.9.2"
14
+      }
15
+    },
16
+    "node_modules/ansi-styles": {
17
+      "version": "3.2.1",
18
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
19
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
20
+      "dependencies": {
21
+        "color-convert": "^1.9.0"
22
+      },
23
+      "engines": {
24
+        "node": ">=4"
25
+      }
26
+    },
27
+    "node_modules/balanced-match": {
28
+      "version": "1.0.2",
29
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
30
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
31
+    },
32
+    "node_modules/brace-expansion": {
33
+      "version": "1.1.11",
34
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
35
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
36
+      "dependencies": {
37
+        "balanced-match": "^1.0.0",
38
+        "concat-map": "0.0.1"
39
+      }
40
+    },
41
+    "node_modules/chalk": {
42
+      "version": "2.4.2",
43
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
44
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
45
+      "dependencies": {
46
+        "ansi-styles": "^3.2.1",
47
+        "escape-string-regexp": "^1.0.5",
48
+        "supports-color": "^5.3.0"
49
+      },
50
+      "engines": {
51
+        "node": ">=4"
52
+      }
53
+    },
54
+    "node_modules/color-convert": {
55
+      "version": "1.9.3",
56
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
57
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
58
+      "dependencies": {
59
+        "color-name": "1.1.3"
60
+      }
61
+    },
62
+    "node_modules/color-name": {
63
+      "version": "1.1.3",
64
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
65
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
66
+    },
67
+    "node_modules/concat-map": {
68
+      "version": "0.0.1",
69
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
70
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
71
+    },
72
+    "node_modules/escape-string-regexp": {
73
+      "version": "1.0.5",
74
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
75
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
76
+      "engines": {
77
+        "node": ">=0.8.0"
78
+      }
79
+    },
80
+    "node_modules/fs.realpath": {
81
+      "version": "1.0.0",
82
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
83
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
84
+    },
85
+    "node_modules/function-bind": {
86
+      "version": "1.1.1",
87
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
88
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
89
+    },
90
+    "node_modules/gently-copy": {
91
+      "version": "3.2.0",
92
+      "resolved": "https://registry.npmjs.org/gently-copy/-/gently-copy-3.2.0.tgz",
93
+      "integrity": "sha512-IBLU4rCffg0Dvq3/7KyiPionCCdEdKnyfe94c00C8+VbgzIS2J9L2jHdLchG9sn8lDqBGzbvfuYVZB/ZlffS7g==",
94
+      "dependencies": {
95
+        "chalk": "^2.4.2",
96
+        "shelljs": "^0.8.3"
97
+      },
98
+      "engines": {
99
+        "node": ">= 4"
100
+      }
101
+    },
102
+    "node_modules/glob": {
103
+      "version": "7.2.3",
104
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
105
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
106
+      "dependencies": {
107
+        "fs.realpath": "^1.0.0",
108
+        "inflight": "^1.0.4",
109
+        "inherits": "2",
110
+        "minimatch": "^3.1.1",
111
+        "once": "^1.3.0",
112
+        "path-is-absolute": "^1.0.0"
113
+      },
114
+      "engines": {
115
+        "node": "*"
116
+      },
117
+      "funding": {
118
+        "url": "https://github.com/sponsors/isaacs"
119
+      }
120
+    },
121
+    "node_modules/has": {
122
+      "version": "1.0.3",
123
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
124
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
125
+      "dependencies": {
126
+        "function-bind": "^1.1.1"
127
+      },
128
+      "engines": {
129
+        "node": ">= 0.4.0"
130
+      }
131
+    },
132
+    "node_modules/has-flag": {
133
+      "version": "3.0.0",
134
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
135
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
136
+      "engines": {
137
+        "node": ">=4"
138
+      }
139
+    },
140
+    "node_modules/htmx.org": {
141
+      "version": "1.9.2",
142
+      "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-1.9.2.tgz",
143
+      "integrity": "sha512-ZGbucKcalQyXdGUl+4Zt3xdRDPmNy70yNhMyDG1eDYUm/ImxmSo2rhIBDa53XitrAVhA+/CGgry+wJ1SO77wrA=="
144
+    },
145
+    "node_modules/inflight": {
146
+      "version": "1.0.6",
147
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
148
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
149
+      "dependencies": {
150
+        "once": "^1.3.0",
151
+        "wrappy": "1"
152
+      }
153
+    },
154
+    "node_modules/inherits": {
155
+      "version": "2.0.4",
156
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
157
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
158
+    },
159
+    "node_modules/interpret": {
160
+      "version": "1.4.0",
161
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
162
+      "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
163
+      "engines": {
164
+        "node": ">= 0.10"
165
+      }
166
+    },
167
+    "node_modules/is-core-module": {
168
+      "version": "2.12.1",
169
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
170
+      "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
171
+      "dependencies": {
172
+        "has": "^1.0.3"
173
+      },
174
+      "funding": {
175
+        "url": "https://github.com/sponsors/ljharb"
176
+      }
177
+    },
178
+    "node_modules/minimatch": {
179
+      "version": "3.1.2",
180
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
181
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
182
+      "dependencies": {
183
+        "brace-expansion": "^1.1.7"
184
+      },
185
+      "engines": {
186
+        "node": "*"
187
+      }
188
+    },
189
+    "node_modules/once": {
190
+      "version": "1.4.0",
191
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
192
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
193
+      "dependencies": {
194
+        "wrappy": "1"
195
+      }
196
+    },
197
+    "node_modules/path-is-absolute": {
198
+      "version": "1.0.1",
199
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
200
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
201
+      "engines": {
202
+        "node": ">=0.10.0"
203
+      }
204
+    },
205
+    "node_modules/path-parse": {
206
+      "version": "1.0.7",
207
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
208
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
209
+    },
210
+    "node_modules/rechoir": {
211
+      "version": "0.6.2",
212
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
213
+      "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
214
+      "dependencies": {
215
+        "resolve": "^1.1.6"
216
+      },
217
+      "engines": {
218
+        "node": ">= 0.10"
219
+      }
220
+    },
221
+    "node_modules/resolve": {
222
+      "version": "1.22.2",
223
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
224
+      "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
225
+      "dependencies": {
226
+        "is-core-module": "^2.11.0",
227
+        "path-parse": "^1.0.7",
228
+        "supports-preserve-symlinks-flag": "^1.0.0"
229
+      },
230
+      "bin": {
231
+        "resolve": "bin/resolve"
232
+      },
233
+      "funding": {
234
+        "url": "https://github.com/sponsors/ljharb"
235
+      }
236
+    },
237
+    "node_modules/shelljs": {
238
+      "version": "0.8.5",
239
+      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
240
+      "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
241
+      "dependencies": {
242
+        "glob": "^7.0.0",
243
+        "interpret": "^1.0.0",
244
+        "rechoir": "^0.6.2"
245
+      },
246
+      "bin": {
247
+        "shjs": "bin/shjs"
248
+      },
249
+      "engines": {
250
+        "node": ">=4"
251
+      }
252
+    },
253
+    "node_modules/supports-color": {
254
+      "version": "5.5.0",
255
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
256
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
257
+      "dependencies": {
258
+        "has-flag": "^3.0.0"
259
+      },
260
+      "engines": {
261
+        "node": ">=4"
262
+      }
263
+    },
264
+    "node_modules/supports-preserve-symlinks-flag": {
265
+      "version": "1.0.0",
266
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
267
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
268
+      "engines": {
269
+        "node": ">= 0.4"
270
+      },
271
+      "funding": {
272
+        "url": "https://github.com/sponsors/ljharb"
273
+      }
274
+    },
275
+    "node_modules/wrappy": {
276
+      "version": "1.0.2",
277
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
278
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
279
+    }
280
+  }
281
+}
0 282
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+htmx.defineExtension('ajax-header', {
2
+    onEvent: function (name, evt) {
3
+        if (name === "htmx:configRequest") {
4
+            evt.detail.headers['X-Requested-With'] = 'XMLHttpRequest';
5
+        }
6
+    }
7
+});
0 8
\ No newline at end of file
1 9
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+htmx.defineExtension('alpine-morph', {
2
+    isInlineSwap: function (swapStyle) {
3
+        return swapStyle === 'morph';
4
+    },
5
+    handleSwap: function (swapStyle, target, fragment) {
6
+        if (swapStyle === 'morph') {
7
+            if (fragment.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
8
+                Alpine.morph(target, fragment.firstElementChild);
9
+                return [target];
10
+            } else {
11
+                Alpine.morph(target, fragment.outerHTML);
12
+                return [target];
13
+            }
14
+        }
15
+    }
16
+});
0 17
\ No newline at end of file
1 18
new file mode 100644
... ...
@@ -0,0 +1,92 @@
1
+(function () {
2
+
3
+    function splitOnWhitespace(trigger) {
4
+        return trigger.split(/\s+/);
5
+    }
6
+
7
+    function parseClassOperation(trimmedValue) {
8
+        var split = splitOnWhitespace(trimmedValue);
9
+        if (split.length > 1) {
10
+            var operation = split[0];
11
+            var classDef = split[1].trim();
12
+            var cssClass;
13
+            var delay;
14
+            if (classDef.indexOf(":") > 0) {
15
+                var splitCssClass = classDef.split(':');
16
+                cssClass = splitCssClass[0];
17
+                delay = htmx.parseInterval(splitCssClass[1]);
18
+            } else {
19
+                cssClass = classDef;
20
+                delay = 100;
21
+            }
22
+            return {
23
+                operation: operation,
24
+                cssClass: cssClass,
25
+                delay: delay
26
+            }
27
+        } else {
28
+            return null;
29
+        }
30
+    }
31
+
32
+    function performOperation(elt, classOperation, classList, currentRunTime) {
33
+        setTimeout(function () {
34
+            elt.classList[classOperation.operation].call(elt.classList, classOperation.cssClass);
35
+        }, currentRunTime)
36
+    }
37
+
38
+    function toggleOperation(elt, classOperation, classList, currentRunTime) {
39
+        setTimeout(function () {
40
+            setInterval(function () {
41
+                elt.classList[classOperation.operation].call(elt.classList, classOperation.cssClass);
42
+            }, classOperation.delay);
43
+        }, currentRunTime)
44
+    }
45
+
46
+    function processClassList(elt, classList) {
47
+        var runs = classList.split("&");
48
+        for (var i = 0; i < runs.length; i++) {
49
+            var run = runs[i];
50
+            var currentRunTime = 0;
51
+            var classOperations = run.split(",");
52
+            for (var j = 0; j < classOperations.length; j++) {
53
+                var value = classOperations[j];
54
+                var trimmedValue = value.trim();
55
+                var classOperation = parseClassOperation(trimmedValue);
56
+                if (classOperation) {
57
+                    if (classOperation.operation === "toggle") {
58
+                        toggleOperation(elt, classOperation, classList, currentRunTime);
59
+                        currentRunTime = currentRunTime + classOperation.delay;
60
+                    } else {
61
+                        currentRunTime = currentRunTime + classOperation.delay;
62
+                        performOperation(elt, classOperation, classList, currentRunTime);
63
+                    }
64
+                }
65
+            }
66
+        }
67
+    }
68
+
69
+    function maybeProcessClasses(elt) {
70
+        if (elt.getAttribute) {
71
+            var classList = elt.getAttribute("classes") || elt.getAttribute("data-classes");
72
+            if (classList) {
73
+                processClassList(elt, classList);
74
+            }
75
+        }
76
+    }
77
+
78
+    htmx.defineExtension('class-tools', {
79
+        onEvent: function (name, evt) {
80
+            if (name === "htmx:afterProcessNode") {
81
+                var elt = evt.detail.elt;
82
+                maybeProcessClasses(elt);
83
+                if (elt.querySelectorAll) {
84
+                    var children = elt.querySelectorAll("[classes], [data-classes]");
85
+                    for (var i = 0; i < children.length; i++) {
86
+                        maybeProcessClasses(children[i]);
87
+                    }
88
+                }
89
+            }
90
+        }
91
+    });
92
+})();
0 93
\ No newline at end of file
1 94
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+htmx.defineExtension('client-side-templates', {
2
+    transformResponse : function(text, xhr, elt) {
3
+
4
+        var mustacheTemplate = htmx.closest(elt, "[mustache-template]");
5
+        if (mustacheTemplate) {
6
+            var data = JSON.parse(text);
7
+            var templateId = mustacheTemplate.getAttribute('mustache-template');
8
+            var template = htmx.find("#" + templateId);
9
+            if (template) {
10
+                return Mustache.render(template.innerHTML, data);
11
+            } else {
12
+                throw "Unknown mustache template: " + templateId;
13
+            }
14
+        }
15
+
16
+        var handlebarsTemplate = htmx.closest(elt, "[handlebars-template]");
17
+        if (handlebarsTemplate) {
18
+            var data = JSON.parse(text);
19
+            var templateName = handlebarsTemplate.getAttribute('handlebars-template');
20
+            return Handlebars.partials[templateName](data);
21
+        }
22
+
23
+        var nunjucksTemplate = htmx.closest(elt, "[nunjucks-template]");
24
+        if (nunjucksTemplate) {
25
+            var data = JSON.parse(text);
26
+            var templateName = nunjucksTemplate.getAttribute('nunjucks-template');
27
+            var template = htmx.find('#' + templateName);
28
+            if (template) {
29
+                return nunjucks.renderString(template.innerHTML, data);
30
+            } else {
31
+                return nunjucks.render(templateName, data);
32
+            }
33
+          }
34
+
35
+        return text;
36
+    }
37
+});
0 38
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+htmx.defineExtension('debug', {
2
+    onEvent: function (name, evt) {
3
+        if (console.debug) {
4
+            console.debug(name, evt);
5
+        } else if (console) {
6
+            console.log("DEBUG:", name, evt);
7
+        } else {
8
+            throw "NO CONSOLE SUPPORTED"
9
+        }
10
+    }
11
+});
0 12
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+"use strict";
2
+
3
+// Disable Submit Button
4
+htmx.defineExtension('disable-element', {
5
+    onEvent: function (name, evt) {
6
+        let elt = evt.detail.elt;
7
+        let target = elt.getAttribute("hx-disable-element");
8
+        let targetElement = (target == "self") ? elt : document.querySelector(target);
9
+
10
+        if (name === "htmx:beforeRequest" && targetElement) {
11
+            targetElement.disabled = true;
12
+        } else if (name == "htmx:afterRequest" && targetElement) {
13
+            targetElement.disabled = false;
14
+        }
15
+    }
16
+});
0 17
\ No newline at end of file
1 18
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+(function(){
2
+    function stringifyEvent(event) {
3
+        var obj = {};
4
+        for (var key in event) {
5
+            obj[key] = event[key];
6
+        }
7
+        return JSON.stringify(obj, function(key, value){
8
+            if(value instanceof Node){
9
+                var nodeRep = value.tagName;
10
+                if (nodeRep) {
11
+                    nodeRep = nodeRep.toLowerCase();
12
+                    if(value.id){
13
+                        nodeRep += "#" + value.id;
14
+                    }
15
+                    if(value.classList && value.classList.length){
16
+                        nodeRep += "." + value.classList.toString().replace(" ", ".")
17
+                    }
18
+                    return nodeRep;
19
+                } else {
20
+                    return "Node"
21
+                }
22
+            }
23
+            if (value instanceof Window) return 'Window';
24
+            return value;
25
+        });
26
+    }
27
+
28
+    htmx.defineExtension('event-header', {
29
+        onEvent: function (name, evt) {
30
+            if (name === "htmx:configRequest") {
31
+                if (evt.detail.triggeringEvent) {
32
+                    evt.detail.headers['Triggering-Event'] = stringifyEvent(evt.detail.triggeringEvent);
33
+                }
34
+            }
35
+        }
36
+    });
37
+})();
0 38
new file mode 100644
... ...
@@ -0,0 +1,141 @@
1
+//==========================================================
2
+// head-support.js
3
+//
4
+// An extension to htmx 1.0 to add head tag merging.
5
+//==========================================================
6
+(function(){
7
+
8
+    var api = null;
9
+
10
+    function log() {
11
+        //console.log(arguments);
12
+    }
13
+
14
+    function mergeHead(newContent, defaultMergeStrategy) {
15
+
16
+        if (newContent && newContent.indexOf('<head') > -1) {
17
+            const htmlDoc = document.createElement("html");
18
+            // remove svgs to avoid conflicts
19
+            var contentWithSvgsRemoved = newContent.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim, '');
20
+            // extract head tag
21
+            var headTag = contentWithSvgsRemoved.match(/(<head(\s[^>]*>|>)([\s\S]*?)<\/head>)/im);
22
+
23
+            // if the  head tag exists...
24
+            if (headTag) {
25
+
26
+                var added = []
27
+                var removed = []
28
+                var preserved = []
29
+                var nodesToAppend = []
30
+
31
+                htmlDoc.innerHTML = headTag;
32
+                var newHeadTag = htmlDoc.querySelector("head");
33
+                var currentHead = document.head;
34
+
35
+                if (newHeadTag == null) {
36
+                    return;
37
+                } else {
38
+                    // put all new head elements into a Map, by their outerHTML
39
+                    var srcToNewHeadNodes = new Map();
40
+                    for (const newHeadChild of newHeadTag.children) {
41
+                        srcToNewHeadNodes.set(newHeadChild.outerHTML, newHeadChild);
42
+                    }
43
+                }
44
+
45
+
46
+
47
+                // determine merge strategy
48
+                var mergeStrategy = api.getAttributeValue(newHeadTag, "hx-head") || defaultMergeStrategy;
49
+
50
+                // get the current head
51
+                for (const currentHeadElt of currentHead.children) {
52
+
53
+                    // If the current head element is in the map
54
+                    var inNewContent = srcToNewHeadNodes.has(currentHeadElt.outerHTML);
55
+                    var isReAppended = currentHeadElt.getAttribute("hx-head") === "re-eval";
56
+                    var isPreserved = api.getAttributeValue(currentHeadElt, "hx-preserve") === "true";
57
+                    if (inNewContent || isPreserved) {
58
+                        if (isReAppended) {
59
+                            // remove the current version and let the new version replace it and re-execute
60
+                            removed.push(currentHeadElt);
61
+                        } else {
62
+                            // this element already exists and should not be re-appended, so remove it from
63
+                            // the new content map, preserving it in the DOM
64
+                            srcToNewHeadNodes.delete(currentHeadElt.outerHTML);
65
+                            preserved.push(currentHeadElt);
66
+                        }
67
+                    } else {
68
+                        if (mergeStrategy === "append") {
69
+                            // we are appending and this existing element is not new content
70
+                            // so if and only if it is marked for re-append do we do anything
71
+                            if (isReAppended) {
72
+                                removed.push(currentHeadElt);
73
+                                nodesToAppend.push(currentHeadElt);
74
+                            }
75
+                        } else {
76
+                            // if this is a merge, we remove this content since it is not in the new head
77
+                            if (api.triggerEvent(document.body, "htmx:removingHeadElement", {headElement: currentHeadElt}) !== false) {
78
+                                removed.push(currentHeadElt);
79
+                            }
80
+                        }
81
+                    }
82
+                }
83
+
84
+                // Push the tremaining new head elements in the Map into the
85
+                // nodes to append to the head tag
86
+                nodesToAppend.push(...srcToNewHeadNodes.values());
87
+                log("to append: ", nodesToAppend);
88
+
89
+                for (const newNode of nodesToAppend) {
90
+                    log("adding: ", newNode);
91
+                    var newElt = document.createRange().createContextualFragment(newNode.outerHTML);
92
+                    log(newElt);
93
+                    if (api.triggerEvent(document.body, "htmx:addingHeadElement", {headElement: newElt}) !== false) {
94
+                        currentHead.appendChild(newElt);
95
+                        added.push(newElt);
96
+                    }
97
+                }
98
+
99
+                // remove all removed elements, after we have appended the new elements to avoid
100
+                // additional network requests for things like style sheets
101
+                for (const removedElement of removed) {
102
+                    if (api.triggerEvent(document.body, "htmx:removingHeadElement", {headElement: removedElement}) !== false) {
103
+                        currentHead.removeChild(removedElement);
104
+                    }
105
+                }
106
+
107
+                api.triggerEvent(document.body, "htmx:afterHeadMerge", {added: added, kept: preserved, removed: removed});
108
+            }
109
+        }
110
+    }
111
+
112
+    htmx.defineExtension("head-support", {
113
+        init: function(apiRef) {
114
+            // store a reference to the internal API.
115
+            api = apiRef;
116
+
117
+            htmx.on('htmx:afterSwap', function(evt){
118
+                var serverResponse = evt.detail.xhr.response;
119
+                if (api.triggerEvent(document.body, "htmx:beforeHeadMerge", evt.detail)) {
120
+                    mergeHead(serverResponse, evt.detail.boosted ? "merge" : "append");
121
+                }
122
+            })
123
+
124
+            htmx.on('htmx:historyRestore', function(evt){
125
+                if (api.triggerEvent(document.body, "htmx:beforeHeadMerge", evt.detail)) {
126
+                    if (evt.detail.cacheMiss) {
127
+                        mergeHead(evt.detail.serverResponse, "merge");
128
+                    } else {
129
+                        mergeHead(evt.detail.item.head, "merge");
130
+                    }
131
+                }
132
+            })
133
+
134
+            htmx.on('htmx:historyItemCreated', function(evt){
135
+                var historyItem = evt.detail.item;
136
+                historyItem.head = document.head.outerHTML;
137
+            })
138
+        }
139
+    });
140
+
141
+})()
0 142
\ No newline at end of file
1 143
new file mode 100644
... ...
@@ -0,0 +1,24 @@
1
+(function(){
2
+
3
+    function mergeObjects(obj1, obj2) {
4
+        for (var key in obj2) {
5
+            if (obj2.hasOwnProperty(key)) {
6
+                obj1[key] = obj2[key];
7
+            }
8
+        }
9
+        return obj1;
10
+    }
11
+
12
+    htmx.defineExtension('include-vals', {
13
+        onEvent: function (name, evt) {
14
+            if (name === "htmx:configRequest") {
15
+                var includeValsElt = htmx.closest(evt.detail.elt, "[include-vals],[data-include-vals]");
16
+                if (includeValsElt) {
17
+                    var includeVals = includeValsElt.getAttribute("include-vals") || includeValsElt.getAttribute("data-include-vals");
18
+                    var valuesToInclude = eval("({" + includeVals + "})");
19
+                    mergeObjects(evt.detail.parameters, valuesToInclude);
20
+                }
21
+            }
22
+        }
23
+    });
24
+})();
0 25
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+htmx.defineExtension('json-enc', {
2
+    onEvent: function (name, evt) {
3
+        if (name === "htmx:configRequest") {
4
+            evt.detail.headers['Content-Type'] = "application/json";
5
+        }
6
+    },
7
+    
8
+    encodeParameters : function(xhr, parameters, elt) {
9
+        xhr.overrideMimeType('text/json');
10
+        return (JSON.stringify(parameters));
11
+    }
12
+});
0 13
\ No newline at end of file
1 14
new file mode 100644
... ...
@@ -0,0 +1,179 @@
1
+;(function () {
2
+	let loadingStatesUndoQueue = []
3
+
4
+	function loadingStateContainer(target) {
5
+		return htmx.closest(target, '[data-loading-states]') || document.body
6
+	}
7
+
8
+	function mayProcessUndoCallback(target, callback) {
9
+		if (document.body.contains(target)) {
10
+			callback()
11
+		}
12
+	}
13
+
14
+	function mayProcessLoadingStateByPath(elt, requestPath) {
15
+		const pathElt = htmx.closest(elt, '[data-loading-path]')
16
+		if (!pathElt) {
17
+			return true
18
+		}
19
+
20
+		return pathElt.getAttribute('data-loading-path') === requestPath
21
+	}
22
+
23
+	function queueLoadingState(sourceElt, targetElt, doCallback, undoCallback) {
24
+		const delayElt = htmx.closest(sourceElt, '[data-loading-delay]')
25
+		if (delayElt) {
26
+			const delayInMilliseconds =
27
+				delayElt.getAttribute('data-loading-delay') || 200
28
+			const timeout = setTimeout(() => {
29
+				doCallback()
30
+
31
+				loadingStatesUndoQueue.push(() => {
32
+					mayProcessUndoCallback(targetElt, () => undoCallback())
33
+				})
34
+			}, delayInMilliseconds)
35
+
36
+			loadingStatesUndoQueue.push(() => {
37
+				mayProcessUndoCallback(targetElt, () => clearTimeout(timeout))
38
+			})
39
+		} else {
40
+			doCallback()
41
+			loadingStatesUndoQueue.push(() => {
42
+				mayProcessUndoCallback(targetElt, () => undoCallback())
43
+			})
44
+		}
45
+	}
46
+
47
+	function getLoadingStateElts(loadingScope, type, path) {
48
+		return Array.from(htmx.findAll(loadingScope, `[${type}]`)).filter(
49
+			(elt) => mayProcessLoadingStateByPath(elt, path)
50
+		)
51
+	}
52
+
53
+	function getLoadingTarget(elt) {
54
+		if (elt.getAttribute('data-loading-target')) {
55
+			return Array.from(
56
+				htmx.findAll(elt.getAttribute('data-loading-target'))
57
+			)
58
+		}
59
+		return [elt]
60
+	}
61
+
62
+	htmx.defineExtension('loading-states', {
63
+		onEvent: function (name, evt) {
64
+			if (name === 'htmx:beforeRequest') {
65
+				const container = loadingStateContainer(evt.target)
66
+
67
+				const loadingStateTypes = [
68
+					'data-loading',
69
+					'data-loading-class',
70
+					'data-loading-class-remove',
71
+					'data-loading-disable',
72
+					'data-loading-aria-busy',
73
+				]
74
+
75
+				let loadingStateEltsByType = {}
76
+
77
+				loadingStateTypes.forEach((type) => {
78
+					loadingStateEltsByType[type] = getLoadingStateElts(
79
+						container,
80
+						type,
81
+						evt.detail.pathInfo.requestPath
82
+					)
83
+				})
84
+
85
+				loadingStateEltsByType['data-loading'].forEach((sourceElt) => {
86
+					getLoadingTarget(sourceElt).forEach((targetElt) => {
87
+						queueLoadingState(
88
+							sourceElt,
89
+							targetElt,
90
+							() =>
91
+								(targetElt.style.display =
92
+									sourceElt.getAttribute('data-loading') ||
93
+									'inline-block'),
94
+							() => (targetElt.style.display = 'none')
95
+						)
96
+					})
97
+				})
98
+
99
+				loadingStateEltsByType['data-loading-class'].forEach(
100
+					(sourceElt) => {
101
+						const classNames = sourceElt
102
+							.getAttribute('data-loading-class')
103
+							.split(' ')
104
+
105
+						getLoadingTarget(sourceElt).forEach((targetElt) => {
106
+							queueLoadingState(
107
+								sourceElt,
108
+								targetElt,
109
+								() =>
110
+									classNames.forEach((className) =>
111
+										targetElt.classList.add(className)
112
+									),
113
+								() =>
114
+									classNames.forEach((className) =>
115
+										targetElt.classList.remove(className)
116
+									)
117
+							)
118
+						})
119
+					}
120
+				)
121
+
122
+				loadingStateEltsByType['data-loading-class-remove'].forEach(
123
+					(sourceElt) => {
124
+						const classNames = sourceElt
125
+							.getAttribute('data-loading-class-remove')
126
+							.split(' ')
127
+
128
+						getLoadingTarget(sourceElt).forEach((targetElt) => {
129
+							queueLoadingState(
130
+								sourceElt,
131
+								targetElt,
132
+								() =>
133
+									classNames.forEach((className) =>
134
+										targetElt.classList.remove(className)
135
+									),
136
+								() =>
137
+									classNames.forEach((className) =>
138
+										targetElt.classList.add(className)
139
+									)
140
+							)
141
+						})
142
+					}
143
+				)
144
+
145
+				loadingStateEltsByType['data-loading-disable'].forEach(
146
+					(sourceElt) => {
147
+						getLoadingTarget(sourceElt).forEach((targetElt) => {
148
+							queueLoadingState(
149
+								sourceElt,
150
+								targetElt,
151
+								() => (targetElt.disabled = true),
152
+								() => (targetElt.disabled = false)
153
+							)
154
+						})
155
+					}
156
+				)
157
+
158
+				loadingStateEltsByType['data-loading-aria-busy'].forEach(
159
+					(sourceElt) => {
160
+						getLoadingTarget(sourceElt).forEach((targetElt) => {
161
+							queueLoadingState(
162
+								sourceElt,
163
+								targetElt,
164
+								() => (targetElt.setAttribute("aria-busy", "true")),
165
+								() => (targetElt.removeAttribute("aria-busy"))
166
+							)
167
+						})
168
+					}
169
+				)
170
+			}
171
+
172
+			if (name === 'htmx:beforeOnLoad') {
173
+				while (loadingStatesUndoQueue.length > 0) {
174
+					loadingStatesUndoQueue.shift()()
175
+				}
176
+			}
177
+		},
178
+	})
179
+})()
0 180
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+htmx.defineExtension('method-override', {
2
+    onEvent: function (name, evt) {
3
+        if (name === "htmx:configRequest") {
4
+            var method = evt.detail.verb;
5
+            if (method !== "get" || method !== "post") {
6
+                evt.detail.headers['X-HTTP-Method-Override'] = method.toUpperCase();
7
+                evt.detail.verb = "post";
8
+            }
9
+        }
10
+    }
11
+});
0 12
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+htmx.defineExtension('morphdom-swap', {
2
+    isInlineSwap: function(swapStyle) {
3
+        return swapStyle === 'morphdom';
4
+    },
5
+    handleSwap: function (swapStyle, target, fragment) {
6
+        if (swapStyle === 'morphdom') {
7
+            if (fragment.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
8
+                morphdom(target, fragment.firstElementChild);
9
+                return [target];
10
+            } else {
11
+                morphdom(target, fragment.outerHTML);
12
+                return [target];
13
+            }
14
+        }
15
+    }
16
+});
0 17
new file mode 100644
... ...
@@ -0,0 +1,45 @@
1
+(function () {
2
+
3
+    /** @type {import("../htmx").HtmxInternalApi} */
4
+    var api;
5
+
6
+    htmx.defineExtension('multi-swap', {
7
+        init: function (apiRef) {
8
+            api = apiRef;
9
+        },
10
+        isInlineSwap: function (swapStyle) {
11
+            return swapStyle.indexOf('multi:') === 0;
12
+        },
13
+        handleSwap: function (swapStyle, target, fragment, settleInfo) {
14
+            if (swapStyle.indexOf('multi:') === 0) {
15
+                var selectorToSwapStyle = {};
16
+                var elements = swapStyle.replace(/^multi\s*:\s*/, '').split(/\s*,\s*/);
17
+
18
+                elements.map(function (element) {
19
+                    var split = element.split(/\s*:\s*/);
20
+                    var elementSelector = split[0];
21
+                    var elementSwapStyle = typeof (split[1]) !== "undefined" ? split[1] : "innerHTML";
22
+
23
+                    if (elementSelector.charAt(0) !== '#') {
24
+                        console.error("HTMX multi-swap: unsupported selector '" + elementSelector + "'. Only ID selectors starting with '#' are supported.");
25
+                        return;
26
+                    }
27
+
28
+                    selectorToSwapStyle[elementSelector] = elementSwapStyle;
29
+                });
30
+
31
+                for (var selector in selectorToSwapStyle) {
32
+                    var swapStyle = selectorToSwapStyle[selector];
33
+                    var elementToSwap = fragment.querySelector(selector);
34
+                    if (elementToSwap) {
35
+                        api.oobSwap(swapStyle, elementToSwap, settleInfo);
36
+                    } else {
37
+                        console.warn("HTMX multi-swap: selector '" + selector + "' not found in source content.");
38
+                    }
39
+                }
40
+
41
+                return true;
42
+            }
43
+        }
44
+    });
45
+})();
0 46
\ No newline at end of file
1 47
new file mode 100644
... ...
@@ -0,0 +1,60 @@
1
+(function(undefined){
2
+    'use strict';
3
+
4
+    // Save a reference to the global object (window in the browser)
5
+    var _root = this;
6
+  
7
+    function dependsOn(pathSpec, url) {
8
+        if (pathSpec === "ignore") {
9
+            return false;
10
+        }
11
+        var dependencyPath = pathSpec.split("/");
12
+        var urlPath = url.split("/");
13
+        for (var i = 0; i < urlPath.length; i++) {
14
+            var dependencyElement = dependencyPath.shift();
15
+            var pathElement = urlPath[i];
16
+            if (dependencyElement !== pathElement && dependencyElement !== "*") {
17
+                return false;
18
+            }
19
+            if (dependencyPath.length === 0 || (dependencyPath.length === 1 && dependencyPath[0] === "")) {
20
+                return true;
21
+            }
22
+        }
23
+        return false;
24
+    }
25
+
26
+    function refreshPath(path) {
27
+        var eltsWithDeps = htmx.findAll("[path-deps]");
28
+        for (var i = 0; i < eltsWithDeps.length; i++) {
29
+            var elt = eltsWithDeps[i];
30
+            if (dependsOn(elt.getAttribute('path-deps'), path)) {
31
+                htmx.trigger(elt, "path-deps");
32
+            }
33
+        }      
34
+    }    
35
+
36
+    htmx.defineExtension('path-deps', {
37
+        onEvent: function (name, evt) {
38
+            if (name === "htmx:beforeOnLoad") {
39
+                var config = evt.detail.requestConfig;
40
+                // mutating call
41
+                if (config.verb !== "get" && evt.target.getAttribute('path-deps') !== 'ignore') {
42
+                    refreshPath(config.path);
43
+                }
44
+            } 
45
+        }
46
+    });
47
+
48
+    /**
49
+     *  ********************
50
+     *  Expose functionality
51
+     *  ********************
52
+     */    
53
+
54
+    _root.PathDeps = {
55
+        refresh: function(path) {
56
+            refreshPath(path);
57
+        }
58
+    };
59
+            
60
+}).call(this);
0 61
new file mode 100644
... ...
@@ -0,0 +1,144 @@
1
+// This adds the "preload" extension to htmx.  By default, this will 
2
+// preload the targets of any tags with `href` or `hx-get` attributes 
3
+// if they also have a `preload` attribute as well.  See documentation
4
+// for more details
5
+htmx.defineExtension("preload", {
6
+
7
+	onEvent: function(name, event) {
8
+
9
+		// Only take actions on "htmx:afterProcessNode"
10
+		if (name !== "htmx:afterProcessNode") {
11
+			return;
12
+		}
13
+
14
+		// SOME HELPER FUNCTIONS WE'LL NEED ALONG THE WAY
15
+
16
+		// attr gets the closest non-empty value from the attribute.
17
+		var attr = function(node, property) {
18
+			if (node == undefined) {return undefined;}
19
+			return node.getAttribute(property) || node.getAttribute("data-" + property) || attr(node.parentElement, property)
20
+		}
21
+		
22
+		// load handles the actual HTTP fetch, and uses htmx.ajax in cases where we're 
23
+		// preloading an htmx resource (this sends the same HTTP headers as a regular htmx request)
24
+		var load = function(node) {
25
+
26
+			// Called after a successful AJAX request, to mark the
27
+			// content as loaded (and prevent additional AJAX calls.)
28
+			var done = function(html) {
29
+				if (!node.preloadAlways) {
30
+					node.preloadState = "DONE"
31
+				}
32
+
33
+				if (attr(node, "preload-images") == "true") {
34
+					document.createElement("div").innerHTML = html // create and populate a node to load linked resources, too.
35
+				}
36
+			}
37
+
38
+			return function() {
39
+
40
+				// If this value has already been loaded, then do not try again.
41
+				if (node.preloadState !== "READY") {
42
+					return;
43
+				}
44
+
45
+				// Special handling for HX-GET - use built-in htmx.ajax function
46
+				// so that headers match other htmx requests, then set 
47
+				// node.preloadState = TRUE so that requests are not duplicated
48
+				// in the future
49
+				var hxGet = node.getAttribute("hx-get") || node.getAttribute("data-hx-get")
50
+				if (hxGet) {
51
+					htmx.ajax("GET", hxGet, {handler:function(elt, info) {
52
+						done(info.xhr.responseText);
53
+					}});
54
+					return;
55
+				}
56
+
57
+				// Otherwise, perform a standard xhr request, then set 
58
+				// node.preloadState = TRUE so that requests are not duplicated 
59
+				// in the future.
60
+				if (node.getAttribute("href")) {
61
+					var r = new XMLHttpRequest();
62
+					r.open("GET", node.getAttribute("href"));
63
+					r.onload = function() {done(r.responseText);};
64
+					r.send();
65
+					return;
66
+				}
67
+			}
68
+		}
69
+
70
+		// This function processes a specific node and sets up event handlers.
71
+		// We'll search for nodes and use it below.
72
+		var init = function(node) {
73
+
74
+			// If this node DOES NOT include a "GET" transaction, then there's nothing to do here.
75
+			if (node.getAttribute("href") + node.getAttribute("hx-get") + node.getAttribute("data-hx-get") == "") {
76
+				return;
77
+			}
78
+
79
+			// Guarantee that we only initialize each node once.
80
+			if (node.preloadState !== undefined) {
81
+				return;
82
+			}
83
+			
84
+			// Get event name from config.
85
+			var on = attr(node, "preload") || "mousedown"
86
+			const always = on.indexOf("always") !== -1
87
+			if (always) {
88
+				on = on.replace('always', '').trim()
89
+			}
90
+						
91
+			// FALL THROUGH to here means we need to add an EventListener
92
+	
93
+			// Apply the listener to the node
94
+			node.addEventListener(on, function(evt) {
95
+				if (node.preloadState === "PAUSE") { // Only add one event listener
96
+					node.preloadState = "READY"; // Requred for the `load` function to trigger
97
+
98
+					// Special handling for "mouseover" events.  Wait 100ms before triggering load.
99
+					if (on === "mouseover") {
100
+						window.setTimeout(load(node), 100);
101
+					} else {
102
+						load(node)() // all other events trigger immediately.
103
+					}
104
+				}
105
+			})
106
+
107
+			// Special handling for certain built-in event handlers
108
+			switch (on) {
109
+
110
+				case "mouseover":
111
+					// Mirror `touchstart` events (fires immediately)
112
+					node.addEventListener("touchstart", load(node));
113
+
114
+					// WHhen the mouse leaves, immediately disable the preload
115
+					node.addEventListener("mouseout", function(evt) {
116
+						if ((evt.target === node) && (node.preloadState === "READY")) {
117
+							node.preloadState = "PAUSE";
118
+						}
119
+					})
120
+					break;
121
+
122
+				case "mousedown":
123
+					 // Mirror `touchstart` events (fires immediately)
124
+					node.addEventListener("touchstart", load(node));
125
+					break;
126
+			}
127
+
128
+			// Mark the node as ready to run.
129
+			node.preloadState = "PAUSE";
130
+			node.preloadAlways = always;
131
+			htmx.trigger(node, "preload:init") // This event can be used to load content immediately.
132
+		}
133
+
134
+		// Search for all child nodes that have a "preload" attribute
135
+		event.target.querySelectorAll("[preload]").forEach(function(node) {
136
+
137
+			// Initialize the node with the "preload" attribute
138
+			init(node)
139
+
140
+			// Initialize all child elements that are anchors or have `hx-get` (use with care)
141
+			node.querySelectorAll("a,[hx-get],[data-hx-get]").forEach(init)
142
+		})
143
+	}
144
+})
0 145
new file mode 100644
... ...
@@ -0,0 +1,10 @@
1
+htmx.defineExtension('rails-method', {
2
+    onEvent: function (name, evt) {
3
+        if (name === "configRequest.htmx") {
4
+            var methodOverride = evt.detail.headers['X-HTTP-Method-Override'];
5
+            if (methodOverride) {
6
+                evt.detail.parameters['_method'] = methodOverride;
7
+            }
8
+        }
9
+    }
10
+});
0 11
new file mode 100644
... ...
@@ -0,0 +1,27 @@
1
+(function(){
2
+    function maybeRemoveMe(elt) {
3
+        var timing = elt.getAttribute("remove-me") || elt.getAttribute("data-remove-me");
4
+        if (timing) {
5
+            setTimeout(function () {
6
+                elt.parentElement.removeChild(elt);
7
+            }, htmx.parseInterval(timing));
8
+        }
9
+    }
10
+
11
+    htmx.defineExtension('remove-me', {
12
+        onEvent: function (name, evt) {
13
+            if (name === "htmx:afterProcessNode") {
14
+                var elt = evt.detail.elt;
15
+                if (elt.getAttribute) {
16
+                    maybeRemoveMe(elt);
17
+                    if (elt.querySelectorAll) {
18
+                        var children = elt.querySelectorAll("[remove-me], [data-remove-me]");
19
+                        for (var i = 0; i < children.length; i++) {
20
+                            maybeRemoveMe(children[i]);
21
+                        }
22
+                    }
23
+                }
24
+            }
25
+        }
26
+    });
27
+})();
0 28
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+htmx.defineExtension('restored', {
2
+    onEvent : function(name, evt) {
3
+        if (name === 'htmx:restored'){
4
+            var restoredElts = evt.detail.document.querySelectorAll(
5
+                "[hx-trigger='restored'],[data-hx-trigger='restored']"
6
+            );
7
+            // need a better way to do this, would prefer to just trigger from evt.detail.elt
8
+            var foundElt = Array.from(restoredElts).find(
9
+                (x) => (x.outerHTML === evt.detail.elt.outerHTML)
10
+            );
11
+            var restoredEvent = evt.detail.triggerEvent(foundElt, 'restored');
12
+        }
13
+        return;
14
+    }
15
+})
0 16
\ No newline at end of file
1 17
new file mode 100644
... ...
@@ -0,0 +1,322 @@
1
+/*
2
+Server Sent Events Extension
3
+============================
4
+This extension adds support for Server Sent Events to htmx.  See /www/extensions/sse.md for usage instructions.
5
+
6
+*/
7
+
8
+(function(){
9
+
10
+	/** @type {import("../htmx").HtmxInternalApi} */
11
+	var api;
12
+
13
+	htmx.defineExtension("sse", {
14
+
15
+		/**
16
+		 * Init saves the provided reference to the internal HTMX API.
17
+		 * 
18
+		 * @param {import("../htmx").HtmxInternalApi} api 
19
+		 * @returns void
20
+		 */
21
+		init: function(apiRef) {
22
+			// store a reference to the internal API.
23
+			api = apiRef;
24
+
25
+			// set a function in the public API for creating new EventSource objects
26
+			if (htmx.createEventSource == undefined) {
27
+				htmx.createEventSource = createEventSource;
28
+			}
29
+		},
30
+
31
+		/**
32
+		 * onEvent handles all events passed to this extension.
33
+		 * 
34
+		 * @param {string} name 
35
+		 * @param {Event} evt 
36
+		 * @returns void
37
+		 */
38
+		onEvent: function(name, evt) {
39
+
40
+			switch (name) {
41
+
42
+			// Try to remove remove an EventSource when elements are removed
43
+			case "htmx:beforeCleanupElement":
44
+				var internalData = api.getInternalData(evt.target)
45
+				if (internalData.sseEventSource) {
46
+					internalData.sseEventSource.close();
47
+				}
48
+				return;
49
+
50
+			// Try to create EventSources when elements are processed
51
+			case "htmx:afterProcessNode":
52
+				createEventSourceOnElement(evt.target);
53
+			}
54
+		}
55
+	});
56
+
57
+	///////////////////////////////////////////////
58
+	// HELPER FUNCTIONS
59
+	///////////////////////////////////////////////
60
+
61
+
62
+	/**
63
+	 * createEventSource is the default method for creating new EventSource objects.
64
+	 * it is hoisted into htmx.config.createEventSource to be overridden by the user, if needed.
65
+	 * 
66
+	 * @param {string} url 
67
+	 * @returns EventSource
68
+	 */
69
+	 function createEventSource(url) {
70
+		return new EventSource(url, {withCredentials:true});
71
+	}
72
+
73
+	function splitOnWhitespace(trigger) {
74
+		return trigger.trim().split(/\s+/);
75
+	}
76
+
77
+	function getLegacySSEURL(elt) {
78
+		var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
79
+		if (legacySSEValue) {
80
+			var values = splitOnWhitespace(legacySSEValue);
81
+			for (var i = 0; i < values.length; i++) {
82
+				var value = values[i].split(/:(.+)/);
83
+				if (value[0] === "connect") {
84
+					return value[1];
85
+				}
86
+			}
87
+		}
88
+	}
89
+
90
+	function getLegacySSESwaps(elt) {
91
+		var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
92
+		var returnArr = [];
93
+		if (legacySSEValue) {
94
+			var values = splitOnWhitespace(legacySSEValue);
95
+			for (var i = 0; i < values.length; i++) {
96
+				var value = values[i].split(/:(.+)/);
97
+				if (value[0] === "swap") {
98
+					returnArr.push(value[1]);
99
+				}
100
+			}
101
+		}
102
+		return returnArr;
103
+	}
104
+
105
+	/**
106
+	 * createEventSourceOnElement creates a new EventSource connection on the provided element.
107
+	 * If a usable EventSource already exists, then it is returned.  If not, then a new EventSource
108
+	 * is created and stored in the element's internalData.
109
+	 * @param {HTMLElement} elt
110
+	 * @param {number} retryCount
111
+	 * @returns {EventSource | null}
112
+	 */
113
+	function createEventSourceOnElement(elt, retryCount) {
114
+
115
+		if (elt == null) {
116
+			return null;
117
+		}
118
+
119
+		var internalData = api.getInternalData(elt);
120
+
121
+		// get URL from element's attribute
122
+		var sseURL = api.getAttributeValue(elt, "sse-connect");
123
+
124
+
125
+		if (sseURL == undefined) {
126
+			var legacyURL = getLegacySSEURL(elt)
127
+			if (legacyURL) {
128
+				sseURL = legacyURL;
129
+			} else {
130
+				return null;
131
+			}
132
+		}
133
+
134
+		// Connect to the EventSource
135
+		var source = htmx.createEventSource(sseURL);
136
+		internalData.sseEventSource = source;
137
+
138
+		// Create event handlers
139
+		source.onerror = function (err) {
140
+
141
+			// Log an error event
142
+			api.triggerErrorEvent(elt, "htmx:sseError", {error:err, source:source});
143
+
144
+			// If parent no longer exists in the document, then clean up this EventSource
145
+			if (maybeCloseSSESource(elt)) {
146
+				return;
147
+			}
148
+
149
+			// Otherwise, try to reconnect the EventSource
150
+			if (source.readyState === EventSource.CLOSED) {
151
+				retryCount = retryCount || 0;
152
+				var timeout = Math.random() * (2 ^ retryCount) * 500;
153
+				window.setTimeout(function() {
154
+					createEventSourceOnElement(elt, Math.min(7, retryCount+1));
155
+				}, timeout);
156
+			}			
157
+		};
158
+
159
+		source.onopen = function (evt) {
160
+			api.triggerEvent(elt, "htmx::sseOpen", {source: source});
161
+		}
162
+		
163
+		// Add message handlers for every `sse-swap` attribute
164
+		queryAttributeOnThisOrChildren(elt, "sse-swap").forEach(function(child) {
165
+
166
+			var sseSwapAttr = api.getAttributeValue(child, "sse-swap");
167
+			if (sseSwapAttr) {
168
+				var sseEventNames = sseSwapAttr.split(",");
169
+			} else {
170
+				var sseEventNames = getLegacySSESwaps(child);
171
+			}
172
+
173
+			for (var i = 0 ; i < sseEventNames.length ; i++) {
174
+				var sseEventName = sseEventNames[i].trim();
175
+				var listener = function(event) {
176
+
177
+					// If the parent is missing then close SSE and remove listener
178
+					if (maybeCloseSSESource(elt)) {
179
+						source.removeEventListener(sseEventName, listener);
180
+						return;
181
+					}
182
+
183
+					// swap the response into the DOM and trigger a notification
184
+					swap(child, event.data);
185
+					api.triggerEvent(elt, "htmx:sseMessage", event);
186
+				};
187
+
188
+				// Register the new listener
189
+				api.getInternalData(elt).sseEventListener = listener;
190
+				source.addEventListener(sseEventName, listener);
191
+			}
192
+		});
193
+
194
+		// Add message handlers for every `hx-trigger="sse:*"` attribute
195
+		queryAttributeOnThisOrChildren(elt, "hx-trigger").forEach(function(child) {
196
+
197
+			var sseEventName = api.getAttributeValue(child, "hx-trigger");
198
+			if (sseEventName == null) {
199
+				return;
200
+			}
201
+
202
+			// Only process hx-triggers for events with the "sse:" prefix
203
+			if (sseEventName.slice(0, 4) != "sse:") {
204
+				return;
205
+			}
206
+
207
+			var listener = function(event) {
208
+
209
+				// If parent is missing, then close SSE and remove listener
210
+				if (maybeCloseSSESource(elt)) {
211
+					source.removeEventListener(sseEventName, listener);
212
+					return;
213
+				}
214
+
215
+				// Trigger events to be handled by the rest of htmx
216
+				htmx.trigger(child, sseEventName, event);
217
+				htmx.trigger(child, "htmx:sseMessage", event);
218
+			}
219
+
220
+			// Register the new listener
221
+			api.getInternalData(elt).sseEventListener = listener;
222
+			source.addEventListener(sseEventName.slice(4), listener);
223
+		});
224
+	}
225
+
226
+	/**
227
+	 * maybeCloseSSESource confirms that the parent element still exists.
228
+	 * If not, then any associated SSE source is closed and the function returns true.
229
+	 * 
230
+	 * @param {HTMLElement} elt 
231
+	 * @returns boolean
232
+	 */
233
+	function maybeCloseSSESource(elt) {
234
+		if (!api.bodyContains(elt)) {
235
+			var source = api.getInternalData(elt).sseEventSource;
236
+			if (source != undefined) {
237
+				source.close();
238
+				// source = null
239
+				return true;
240
+			}
241
+		}
242
+		return false;
243
+	}
244
+
245
+	/**
246
+	 * queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT.
247
+	 * 
248
+	 * @param {HTMLElement} elt 
249
+	 * @param {string} attributeName 
250
+	 */
251
+	function queryAttributeOnThisOrChildren(elt, attributeName) {
252
+
253
+		var result = [];
254
+
255
+		// If the parent element also contains the requested attribute, then add it to the results too.
256
+		if (api.hasAttribute(elt, attributeName) || api.hasAttribute(elt, "hx-sse")) {
257
+			result.push(elt);
258
+		}
259
+
260
+		// Search all child nodes that match the requested attribute
261
+		elt.querySelectorAll("[" + attributeName + "], [data-" + attributeName + "], [hx-sse], [data-hx-sse]").forEach(function(node) {
262
+			result.push(node);
263
+		});
264
+
265
+		return result;
266
+	}
267
+
268
+	/**
269
+	 * @param {HTMLElement} elt
270
+	 * @param {string} content 
271
+	 */
272
+	function swap(elt, content) {
273
+
274
+		api.withExtensions(elt, function(extension) {
275
+			content = extension.transformResponse(content, null, elt);
276
+		});
277
+
278
+		var swapSpec = api.getSwapSpecification(elt);
279
+		var target = api.getTarget(elt);
280
+		var settleInfo = api.makeSettleInfo(elt);
281
+
282
+		api.selectAndSwap(swapSpec.swapStyle, target, elt, content, settleInfo);
283
+
284
+		settleInfo.elts.forEach(function (elt) {
285
+			if (elt.classList) {
286
+				elt.classList.add(htmx.config.settlingClass);
287
+			}
288
+			api.triggerEvent(elt, 'htmx:beforeSettle');
289
+		});
290
+
291
+		// Handle settle tasks (with delay if requested)
292
+		if (swapSpec.settleDelay > 0) {
293
+			setTimeout(doSettle(settleInfo), swapSpec.settleDelay);
294
+		} else {
295
+			doSettle(settleInfo)();
296
+		}
297
+	}
298
+
299
+	/**
300
+	 * doSettle mirrors much of the functionality in htmx that 
301
+	 * settles elements after their content has been swapped.
302
+	 * TODO: this should be published by htmx, and not duplicated here
303
+	 * @param {import("../htmx").HtmxSettleInfo} settleInfo 
304
+	 * @returns () => void
305
+	 */
306
+	function doSettle(settleInfo) {
307
+
308
+		return function() {
309
+			settleInfo.tasks.forEach(function (task) {
310
+				task.call();
311
+			});
312
+
313
+			settleInfo.elts.forEach(function (elt) {
314
+				if (elt.classList) {
315
+					elt.classList.remove(htmx.config.settlingClass);
316
+				}
317
+				api.triggerEvent(elt, 'htmx:afterSettle');
318
+			});
319
+		}
320
+	}
321
+
322
+})();
0 323
\ No newline at end of file
1 324
new file mode 100644
... ...
@@ -0,0 +1,477 @@
1
+/*
2
+WebSockets Extension
3
+============================
4
+This extension adds support for WebSockets to htmx.  See /www/extensions/ws.md for usage instructions.
5
+*/
6
+
7
+(function () {
8
+
9
+	/** @type {import("../htmx").HtmxInternalApi} */
10
+	var api;
11
+
12
+	htmx.defineExtension("ws", {
13
+
14
+		/**
15
+		 * init is called once, when this extension is first registered.
16
+		 * @param {import("../htmx").HtmxInternalApi} apiRef
17
+		 */
18
+		init: function (apiRef) {
19
+
20
+			// Store reference to internal API
21
+			api = apiRef;
22
+
23
+			// Default function for creating new EventSource objects
24
+			if (!htmx.createWebSocket) {
25
+				htmx.createWebSocket = createWebSocket;
26
+			}
27
+
28
+			// Default setting for reconnect delay
29
+			if (!htmx.config.wsReconnectDelay) {
30
+				htmx.config.wsReconnectDelay = "full-jitter";
31
+			}
32
+		},
33
+
34
+		/**
35
+		 * onEvent handles all events passed to this extension.
36
+		 *
37
+		 * @param {string} name
38
+		 * @param {Event} evt
39
+		 */
40
+		onEvent: function (name, evt) {
41
+
42
+			switch (name) {
43
+
44
+				// Try to close the socket when elements are removed
45
+				case "htmx:beforeCleanupElement":
46
+
47
+					var internalData = api.getInternalData(evt.target)
48
+
49
+					if (internalData.webSocket) {
50
+						internalData.webSocket.close();
51
+					}
52
+					return;
53
+
54
+				// Try to create websockets when elements are processed
55
+				case "htmx:afterProcessNode":
56
+					var parent = evt.target;
57
+
58
+					forEach(queryAttributeOnThisOrChildren(parent, "ws-connect"), function (child) {
59
+						ensureWebSocket(child)
60
+					});
61
+					forEach(queryAttributeOnThisOrChildren(parent, "ws-send"), function (child) {
62
+						ensureWebSocketSend(child)
63
+					});
64
+			}
65
+		}
66
+	});
67
+
68
+	function splitOnWhitespace(trigger) {
69
+		return trigger.trim().split(/\s+/);
70
+	}
71
+
72
+	function getLegacyWebsocketURL(elt) {
73
+		var legacySSEValue = api.getAttributeValue(elt, "hx-ws");
74
+		if (legacySSEValue) {
75
+			var values = splitOnWhitespace(legacySSEValue);
76
+			for (var i = 0; i < values.length; i++) {
77
+				var value = values[i].split(/:(.+)/);
78
+				if (value[0] === "connect") {
79
+					return value[1];
80
+				}
81
+			}
82
+		}
83
+	}
84
+
85
+	/**
86
+	 * ensureWebSocket creates a new WebSocket on the designated element, using
87
+	 * the element's "ws-connect" attribute.
88
+	 * @param {HTMLElement} socketElt
89
+	 * @returns
90
+	 */
91
+	function ensureWebSocket(socketElt) {
92
+
93
+		// If the element containing the WebSocket connection no longer exists, then
94
+		// do not connect/reconnect the WebSocket.
95
+		if (!api.bodyContains(socketElt)) {
96
+			return;
97
+		}
98
+
99
+		// Get the source straight from the element's value
100
+		var wssSource = api.getAttributeValue(socketElt, "ws-connect")
101
+
102
+		if (wssSource == null || wssSource === "") {
103
+			var legacySource = getLegacyWebsocketURL(socketElt);
104
+			if (legacySource == null) {
105
+				return;
106
+			} else {
107
+				wssSource = legacySource;
108
+			}
109
+		}
110
+
111
+		// Guarantee that the wssSource value is a fully qualified URL
112
+		if (wssSource.indexOf("/") === 0) {
113
+			var base_part = location.hostname + (location.port ? ':' + location.port : '');
114
+			if (location.protocol === 'https:') {
115
+				wssSource = "wss://" + base_part + wssSource;
116
+			} else if (location.protocol === 'http:') {
117
+				wssSource = "ws://" + base_part + wssSource;
118
+			}
119
+		}
120
+
121
+		var socketWrapper = createWebsocketWrapper(socketElt, function () {
122
+			return htmx.createWebSocket(wssSource)
123
+		});
124
+
125
+		socketWrapper.addEventListener('message', function (event) {
126
+			if (maybeCloseWebSocketSource(socketElt)) {
127
+				return;
128
+			}
129
+
130
+			var response = event.data;
131
+			if (!api.triggerEvent(socketElt, "htmx:wsBeforeMessage", {
132
+				message: response,
133
+				socketWrapper: socketWrapper.publicInterface
134
+			})) {
135
+				return;
136
+			}
137
+
138
+			api.withExtensions(socketElt, function (extension) {
139
+				response = extension.transformResponse(response, null, socketElt);
140
+			});
141
+
142
+			var settleInfo = api.makeSettleInfo(socketElt);
143
+			var fragment = api.makeFragment(response);
144
+
145
+			if (fragment.children.length) {
146
+				var children = Array.from(fragment.children);
147
+				for (var i = 0; i < children.length; i++) {
148
+					api.oobSwap(api.getAttributeValue(children[i], "hx-swap-oob") || "true", children[i], settleInfo);
149
+				}
150
+			}
151
+
152
+			api.settleImmediately(settleInfo.tasks);
153
+			api.triggerEvent(socketElt, "htmx:wsAfterMessage", { message: response, socketWrapper: socketWrapper.publicInterface })
154
+		});
155
+
156
+		// Put the WebSocket into the HTML Element's custom data.
157
+		api.getInternalData(socketElt).webSocket = socketWrapper;
158
+	}
159
+
160
+	/**
161
+	 * @typedef {Object} WebSocketWrapper
162
+	 * @property {WebSocket} socket
163
+	 * @property {Array<{message: string, sendElt: Element}>} messageQueue
164
+	 * @property {number} retryCount
165
+	 * @property {(message: string, sendElt: Element) => void} sendImmediately sendImmediately sends message regardless of websocket connection state
166
+	 * @property {(message: string, sendElt: Element) => void} send
167
+	 * @property {(event: string, handler: Function) => void} addEventListener
168
+	 * @property {() => void} handleQueuedMessages
169
+	 * @property {() => void} init
170
+	 * @property {() => void} close
171
+	 */
172
+	/**
173
+	 *
174
+	 * @param socketElt
175
+	 * @param socketFunc
176
+	 * @returns {WebSocketWrapper}
177
+	 */
178
+	function createWebsocketWrapper(socketElt, socketFunc) {
179
+		var wrapper = {
180
+			socket: null,
181
+			messageQueue: [],
182
+			retryCount: 0,
183
+
184
+			/** @type {Object<string, Function[]>} */
185
+			events: {},
186
+
187
+			addEventListener: function (event, handler) {
188
+				if (this.socket) {
189
+					this.socket.addEventListener(event, handler);
190
+				}
191
+
192
+				if (!this.events[event]) {
193
+					this.events[event] = [];
194
+				}
195
+
196
+				this.events[event].push(handler);
197
+			},
198
+
199
+			sendImmediately: function (message, sendElt) {
200
+				if (!this.socket) {
201
+					api.triggerErrorEvent()
202
+				}
203
+				if (sendElt && api.triggerEvent(sendElt, 'htmx:wsBeforeSend', {
204
+					message: message,
205
+					socketWrapper: this.publicInterface
206
+				})) {
207
+					this.socket.send(message);
208
+					sendElt && api.triggerEvent(sendElt, 'htmx:wsAfterSend', {
209
+						message: message,
210
+						socketWrapper: this.publicInterface
211
+					})
212
+				}
213
+			},
214
+
215
+			send: function (message, sendElt) {
216
+				if (this.socket.readyState !== this.socket.OPEN) {
217
+					this.messageQueue.push({ message: message, sendElt: sendElt });
218
+				} else {
219
+					this.sendImmediately(message, sendElt);
220
+				}
221
+			},
222
+
223
+			handleQueuedMessages: function () {
224
+				while (this.messageQueue.length > 0) {
225
+					var queuedItem = this.messageQueue[0]
226
+					if (this.socket.readyState === this.socket.OPEN) {
227
+						this.sendImmediately(queuedItem.message, queuedItem.sendElt);
228
+						this.messageQueue.shift();
229
+					} else {
230
+						break;
231
+					}
232
+				}
233
+			},
234
+
235
+			init: function () {
236
+				if (this.socket && this.socket.readyState === this.socket.OPEN) {
237
+					// Close discarded socket
238
+					this.socket.close()
239
+				}
240
+
241
+				// Create a new WebSocket and event handlers
242
+				/** @type {WebSocket} */
243
+				var socket = socketFunc();
244
+
245
+				// The event.type detail is added for interface conformance with the
246
+				// other two lifecycle events (open and close) so a single handler method
247
+				// can handle them polymorphically, if required.
248
+				api.triggerEvent(socketElt, "htmx:wsConnecting", { event: { type: 'connecting' } });
249
+
250
+				this.socket = socket;
251
+
252
+				socket.onopen = function (e) {
253
+					wrapper.retryCount = 0;
254
+					api.triggerEvent(socketElt, "htmx:wsOpen", { event: e, socketWrapper: wrapper.publicInterface });
255
+					wrapper.handleQueuedMessages();
256
+				}
257
+
258
+				socket.onclose = function (e) {
259
+					// If socket should not be connected, stop further attempts to establish connection
260
+					// If Abnormal Closure/Service Restart/Try Again Later, then set a timer to reconnect after a pause.
261
+					if (!maybeCloseWebSocketSource(socketElt) && [1006, 1012, 1013].indexOf(e.code) >= 0) {
262
+						var delay = getWebSocketReconnectDelay(wrapper.retryCount);
263
+						setTimeout(function () {
264
+							wrapper.retryCount += 1;
265
+							wrapper.init();
266
+						}, delay);
267
+					}
268
+
269
+					// Notify client code that connection has been closed. Client code can inspect `event` field
270
+					// to determine whether closure has been valid or abnormal
271
+					api.triggerEvent(socketElt, "htmx:wsClose", { event: e, socketWrapper: wrapper.publicInterface })
272
+				};
273
+
274
+				socket.onerror = function (e) {
275
+					api.triggerErrorEvent(socketElt, "htmx:wsError", { error: e, socketWrapper: wrapper });
276
+					maybeCloseWebSocketSource(socketElt);
277
+				};
278
+
279
+				var events = this.events;
280
+				Object.keys(events).forEach(function (k) {
281
+					events[k].forEach(function (e) {
282
+						socket.addEventListener(k, e);
283
+					})
284
+				});
285
+			},
286
+
287
+			close: function () {
288
+				this.socket.close()
289
+			}
290
+		}
291
+
292
+		wrapper.init();
293
+
294
+		wrapper.publicInterface = {
295
+			send: wrapper.send.bind(wrapper),
296
+			sendImmediately: wrapper.sendImmediately.bind(wrapper),
297
+			queue: wrapper.messageQueue
298
+		};
299
+
300
+		return wrapper;
301
+	}
302
+
303
+	/**
304
+	 * ensureWebSocketSend attaches trigger handles to elements with
305
+	 * "ws-send" attribute
306
+	 * @param {HTMLElement} elt
307
+	 */
308
+	function ensureWebSocketSend(elt) {
309
+		var legacyAttribute = api.getAttributeValue(elt, "hx-ws");
310
+		if (legacyAttribute && legacyAttribute !== 'send') {
311
+			return;
312
+		}
313
+
314
+		var webSocketParent = api.getClosestMatch(elt, hasWebSocket)
315
+		processWebSocketSend(webSocketParent, elt);
316
+	}
317
+
318
+	/**
319
+	 * hasWebSocket function checks if a node has webSocket instance attached
320
+	 * @param {HTMLElement} node
321
+	 * @returns {boolean}
322
+	 */
323
+	function hasWebSocket(node) {
324
+		return api.getInternalData(node).webSocket != null;
325
+	}
326
+
327
+	/**
328
+	 * processWebSocketSend adds event listeners to the <form> element so that
329
+	 * messages can be sent to the WebSocket server when the form is submitted.
330
+	 * @param {HTMLElement} socketElt
331
+	 * @param {HTMLElement} sendElt
332
+	 */
333
+	function processWebSocketSend(socketElt, sendElt) {
334
+		var nodeData = api.getInternalData(sendElt);
335
+		var triggerSpecs = api.getTriggerSpecs(sendElt);
336
+		triggerSpecs.forEach(function (ts) {
337
+			api.addTriggerHandler(sendElt, ts, nodeData, function (elt, evt) {
338
+				if (maybeCloseWebSocketSource(socketElt)) {
339
+					return;
340
+				}
341
+
342
+				/** @type {WebSocketWrapper} */
343
+				var socketWrapper = api.getInternalData(socketElt).webSocket;
344
+				var headers = api.getHeaders(sendElt, socketElt);
345
+				var results = api.getInputValues(sendElt, 'post');
346
+				var errors = results.errors;
347
+				var rawParameters = results.values;
348
+				var expressionVars = api.getExpressionVars(sendElt);
349
+				var allParameters = api.mergeObjects(rawParameters, expressionVars);
350
+				var filteredParameters = api.filterValues(allParameters, sendElt);
351
+
352
+				var sendConfig = {
353
+					parameters: filteredParameters,
354
+					unfilteredParameters: allParameters,
355
+					headers: headers,
356
+					errors: errors,
357
+
358
+					triggeringEvent: evt,
359
+					messageBody: undefined,
360
+					socketWrapper: socketWrapper.publicInterface
361
+				};
362
+
363
+				if (!api.triggerEvent(elt, 'htmx:wsConfigSend', sendConfig)) {
364
+					return;
365
+				}
366
+
367
+				if (errors && errors.length > 0) {
368
+					api.triggerEvent(elt, 'htmx:validation:halted', errors);
369
+					return;
370
+				}
371
+
372
+				var body = sendConfig.messageBody;
373
+				if (body === undefined) {
374
+					var toSend = Object.assign({}, sendConfig.parameters);
375
+					if (sendConfig.headers)
376
+						toSend['HEADERS'] = headers;
377
+					body = JSON.stringify(toSend);
378
+				}
379
+
380
+				socketWrapper.send(body, elt);
381
+
382
+				if (api.shouldCancel(evt, elt)) {
383
+					evt.preventDefault();
384
+				}
385
+			});
386
+		});
387
+	}
388
+
389
+	/**
390
+	 * getWebSocketReconnectDelay is the default easing function for WebSocket reconnects.
391
+	 * @param {number} retryCount // The number of retries that have already taken place
392
+	 * @returns {number}
393
+	 */
394
+	function getWebSocketReconnectDelay(retryCount) {
395
+
396
+		/** @type {"full-jitter" | ((retryCount:number) => number)} */
397
+		var delay = htmx.config.wsReconnectDelay;
398
+		if (typeof delay === 'function') {
399
+			return delay(retryCount);
400
+		}
401
+		if (delay === 'full-jitter') {
402
+			var exp = Math.min(retryCount, 6);
403
+			var maxDelay = 1000 * Math.pow(2, exp);
404
+			return maxDelay * Math.random();
405
+		}
406
+
407
+		logError('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"');
408
+	}
409
+
410
+	/**
411
+	 * maybeCloseWebSocketSource checks to the if the element that created the WebSocket
412
+	 * still exists in the DOM.  If NOT, then the WebSocket is closed and this function
413
+	 * returns TRUE.  If the element DOES EXIST, then no action is taken, and this function
414
+	 * returns FALSE.
415
+	 *
416
+	 * @param {*} elt
417
+	 * @returns
418
+	 */
419
+	function maybeCloseWebSocketSource(elt) {
420
+		if (!api.bodyContains(elt)) {
421
+			api.getInternalData(elt).webSocket.close();
422
+			return true;
423
+		}
424
+		return false;
425
+	}
426
+
427
+	/**
428
+	 * createWebSocket is the default method for creating new WebSocket objects.
429
+	 * it is hoisted into htmx.createWebSocket to be overridden by the user, if needed.
430
+	 *
431
+	 * @param {string} url
432
+	 * @returns WebSocket
433
+	 */
434
+	function createWebSocket(url) {
435
+		var sock = new WebSocket(url, []);
436
+		sock.binaryType = htmx.config.wsBinaryType;
437
+		return sock;
438
+	}
439
+
440
+	/**
441
+	 * queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT.
442
+	 *
443
+	 * @param {HTMLElement} elt
444
+	 * @param {string} attributeName
445
+	 */
446
+	function queryAttributeOnThisOrChildren(elt, attributeName) {
447
+
448
+		var result = []
449
+
450
+		// If the parent element also contains the requested attribute, then add it to the results too.
451
+		if (api.hasAttribute(elt, attributeName) || api.hasAttribute(elt, "hx-ws")) {
452
+			result.push(elt);
453
+		}
454
+
455
+		// Search all child nodes that match the requested attribute
456
+		elt.querySelectorAll("[" + attributeName + "], [data-" + attributeName + "], [data-hx-ws], [hx-ws]").forEach(function (node) {
457
+			result.push(node)
458
+		})
459
+
460
+		return result
461
+	}
462
+
463
+	/**
464
+	 * @template T
465
+	 * @param {T[]} arr
466
+	 * @param {(T) => void} func
467
+	 */
468
+	function forEach(arr, func) {
469
+		if (arr) {
470
+			for (var i = 0; i < arr.length; i++) {
471
+				func(arr[i]);
472
+			}
473
+		}
474
+	}
475
+
476
+})();
477
+
0 478
new file mode 100644
... ...
@@ -0,0 +1,339 @@
1
+// https://htmx.org/reference/#api
2
+
3
+/**
4
+ * This method adds a class to the given element.
5
+ *
6
+ * https://htmx.org/api/#addClass
7
+ *
8
+ * @param elt the element to add the class to
9
+ * @param clazz the class to add
10
+ * @param delay the delay (in milliseconds before class is added)
11
+ */
12
+export function addClass(elt: Element, clazz: string, delay?: number): void;
13
+
14
+/**
15
+ * Issues an htmx-style AJAX request
16
+ *
17
+ * https://htmx.org/api/#ajax
18
+ *
19
+ * @param verb 'GET', 'POST', etc.
20
+ * @param path the URL path to make the AJAX
21
+ * @param element the element to target (defaults to the **body**)
22
+ */
23
+export function ajax(verb: string, path: string, element: Element): void;
24
+
25
+/**
26
+ * Issues an htmx-style AJAX request
27
+ *
28
+ * https://htmx.org/api/#ajax
29
+ *
30
+ * @param verb 'GET', 'POST', etc.
31
+ * @param path the URL path to make the AJAX
32
+ * @param selector a selector for the target
33
+ */
34
+export function ajax(verb: string, path: string, selector: string): void;
35
+
36
+/**
37
+ * Issues an htmx-style AJAX request
38
+ *
39
+ * https://htmx.org/api/#ajax
40
+ *
41
+ * @param verb 'GET', 'POST', etc.
42
+ * @param path the URL path to make the AJAX
43
+ * @param context a context object that contains any of the following
44
+ */
45
+export function ajax(
46
+    verb: string,
47
+    path: string,
48
+    context: Partial<{ source: any; event: any; handler: any; target: any; values: any; headers: any }>
49
+): void;
50
+
51
+/**
52
+ * Finds the closest matching element in the given elements parentage, inclusive of the element
53
+ *
54
+ * https://htmx.org/api/#closest
55
+ *
56
+ * @param elt the element to find the selector from
57
+ * @param selector the selector to find
58
+ */
59
+export function closest(elt: Element, selector: string): Element | null;
60
+
61
+/**
62
+ * A property holding the configuration htmx uses at runtime.
63
+ *
64
+ * Note that using a [meta tag](https://htmx.org/docs/#config) is the preferred mechanism for setting these properties.
65
+ *
66
+ * https://htmx.org/api/#config
67
+ */
68
+export var config: HtmxConfig;
69
+
70
+/**
71
+ * A property used to create new [Server Sent Event](https://htmx.org/docs/#sse) sources. This can be updated to provide custom SSE setup.
72
+ *
73
+ * https://htmx.org/api/#createEventSource
74
+ */
75
+export var createEventSource: (url: string) => EventSource;
76
+
77
+/**
78
+ * A property used to create new [WebSocket](https://htmx.org/docs/#websockets). This can be updated to provide custom WebSocket setup.
79
+ *
80
+ * https://htmx.org/api/#createWebSocket
81
+ */
82
+export var createWebSocket: (url: string) => WebSocket;
83
+
84
+/**
85
+ * Defines a new htmx [extension](https://htmx.org/extensions).
86
+ *
87
+ * https://htmx.org/api/#defineExtension
88
+ *
89
+ * @param name the extension name
90
+ * @param ext the extension definition
91
+ */
92
+export function defineExtension(name: string, ext: HtmxExtension): void;
93
+
94
+/**
95
+ * Finds an element matching the selector
96
+ *
97
+ * https://htmx.org/api/#find
98
+ *
99
+ * @param selector the selector to match
100
+ */
101
+export function find(selector: string): Element | null;
102
+
103
+/**
104
+ * Finds an element matching the selector
105
+ *
106
+ * https://htmx.org/api/#find
107
+ *
108
+ * @param elt the root element to find the matching element in, inclusive
109
+ * @param selector the selector to match
110
+ */
111
+export function find(elt: Element, selector: string): Element | null;
112
+
113
+/**
114
+ * Finds all elements matching the selector
115
+ *
116
+ * https://htmx.org/api/#findAll
117
+ *
118
+ * @param selector the selector to match
119
+ */
120
+export function findAll(selector: string): NodeListOf<Element>;
121
+
122
+/**
123
+ * Finds all elements matching the selector
124
+ *
125
+ * https://htmx.org/api/#findAll
126
+ *
127
+ * @param elt the root element to find the matching elements in, inclusive
128
+ * @param selector the selector to match
129
+ */
130
+export function findAll(elt: Element, selector: string): NodeListOf<Element>;
131
+
132
+/**
133
+ * Log all htmx events, useful for debugging.
134
+ *
135
+ * https://htmx.org/api/#logAll
136
+ */
137
+export function logAll(): void;
138
+
139
+/**
140
+ * The logger htmx uses to log with
141
+ *
142
+ * https://htmx.org/api/#logger
143
+ */
144
+export var logger: (elt: Element, eventName: string, detail: any) => void | null;
145
+
146
+/**
147
+ * Removes an event listener from an element
148
+ *
149
+ * https://htmx.org/api/#off
150
+ *
151
+ * @param eventName the event name to remove the listener from
152
+ * @param listener the listener to remove
153
+ */
154
+export function off(eventName: string, listener: (evt: Event) => void): (evt: Event) => void;
155
+
156
+/**
157
+ * Removes an event listener from an element
158
+ *
159
+ * https://htmx.org/api/#off
160
+ *
161
+ * @param target the element to remove the listener from
162
+ * @param eventName the event name to remove the listener from
163
+ * @param listener the listener to remove
164
+ */
165
+export function off(target: string, eventName: string, listener: (evt: Event) => void): (evt: Event) => void;
166
+
167
+/**
168
+ * Adds an event listener to an element
169
+ *
170
+ * https://htmx.org/api/#on
171
+ *
172
+ * @param eventName the event name to add the listener for
173
+ * @param listener the listener to add
174
+ */
175
+export function on(eventName: string, listener: (evt: Event) => void): (evt: Event) => void;
176
+
177
+/**
178
+ * Adds an event listener to an element
179
+ *
180
+ * https://htmx.org/api/#on
181
+ *
182
+ * @param target the element to add the listener to
183
+ * @param eventName the event name to add the listener for
184
+ * @param listener the listener to add
185
+ */
186
+export function on(target: string, eventName: string, listener: (evt: Event) => void): (evt: Event) => void;
187
+
188
+/**
189
+ * Adds a callback for the **htmx:load** event. This can be used to process new content, for example initializing the content with a javascript library
190
+ *
191
+ * https://htmx.org/api/#onLoad
192
+ *
193
+ * @param callback the callback to call on newly loaded content
194
+ */
195
+export function onLoad(callback: (element: Element) => void): void;
196
+
197
+/**
198
+ * Parses an interval string consistent with the way htmx does. Useful for plugins that have timing-related attributes.
199
+ *
200
+ * Caution: Accepts an int followed by either **s** or **ms**. All other values use **parseFloat**
201
+ *
202
+ * https://htmx.org/api/#parseInterval
203
+ *
204
+ * @param str timing string
205
+ */
206
+export function parseInterval(str: string): number;
207
+
208
+/**
209
+ * Processes new content, enabling htmx behavior. This can be useful if you have content that is added to the DOM outside of the normal htmx request cycle but still want htmx attributes to work.
210
+ *
211
+ * https://htmx.org/api/#process
212
+ *
213
+ * @param element element to process
214
+ */
215
+export function process(element: Element): void;
216
+
217
+/**
218
+ * Removes an element from the DOM
219
+ *
220
+ * https://htmx.org/api/#remove
221
+ *
222
+ * @param elt element to remove
223
+ * @param delay the delay (in milliseconds before element is removed)
224
+ */
225
+export function remove(elt: Element, delay?: number): void;
226
+
227
+/**
228
+ * Removes a class from the given element
229
+ *
230
+ * https://htmx.org/api/#removeClass
231
+ *
232
+ * @param elt element to remove the class from
233
+ * @param clazz the class to remove
234
+ * @param delay the delay (in milliseconds before class is removed)
235
+ */
236
+export function removeClass(elt: Element, clazz: string, delay?: number): void;
237
+
238
+/**
239
+ * Removes the given extension from htmx
240
+ *
241
+ * https://htmx.org/api/#removeExtension
242
+ *
243
+ * @param name the name of the extension to remove
244
+ */
245
+export function removeExtension(name: string): void;
246
+
247
+/**
248
+ * Takes the given class from its siblings, so that among its siblings, only the given element will have the class.
249
+ *
250
+ * https://htmx.org/api/#takeClass
251
+ *
252
+ * @param elt the element that will take the class
253
+ * @param clazz the class to take
254
+ */
255
+export function takeClass(elt: Element, clazz: string): void;
256
+
257
+/**
258
+ * Toggles the given class on an element
259
+ *
260
+ * https://htmx.org/api/#toggleClass
261
+ *
262
+ * @param elt the element to toggle the class on
263
+ * @param clazz the class to toggle
264
+ */
265
+export function toggleClass(elt: Element, clazz: string): void;
266
+
267
+/**
268
+ * Triggers a given event on an element
269
+ *
270
+ * https://htmx.org/api/#trigger
271
+ *
272
+ * @param elt the element to trigger the event on
273
+ * @param name the name of the event to trigger
274
+ * @param detail details for the event
275
+ */
276
+export function trigger(elt: Element, name: string, detail: any): void;
277
+
278
+/**
279
+ * Returns the input values that would resolve for a given element via the htmx value resolution mechanism
280
+ *
281
+ * https://htmx.org/api/#values
282
+ *
283
+ * @param elt the element to resolve values on
284
+ * @param requestType the request type (e.g. **get** or **post**) non-GET's will include the enclosing form of the element. Defaults to **post**
285
+ */
286
+export function values(elt: Element, requestType?: string): any;
287
+
288
+export const version: string;
289
+
290
+export interface HtmxConfig {
291
+    /** array of strings: the attributes to settle during the settling phase */
292
+    attributesToSettle?: ["class", "style", "width", "height"] | string[];
293
+    /** the default delay between completing the content swap and settling attributes */
294
+    defaultSettleDelay?: number;
295
+    /** the default delay between receiving a response from the server and doing the swap */
296
+    defaultSwapDelay?: number;
297
+    /** the default swap style to use if **[hx-swap](https://htmx.org/attributes/hx-swap)** is omitted */
298
+    defaultSwapStyle?: "innerHTML" | string;
299
+    /** the number of pages to keep in **localStorage** for history support */
300
+    historyCacheSize?: number;
301
+    /** whether or not to use history */
302
+    historyEnabled?: boolean;
303
+    /** if true, htmx will inject a small amount of CSS into the page to make indicators invisible unless the **htmx-indicator** class is present */
304
+    includeIndicatorStyles?: boolean;
305
+    /** the class to place on indicators when a request is in flight */
306
+    indicatorClass?: "htmx-indicator" | string;
307
+    /** the class to place on triggering elements when a request is in flight */
308
+    requestClass?: "htmx-request" | string;
309
+    /** the class to temporarily place on elements that htmx has added to the DOM */
310
+    addedClass?: "htmx-added" | string;
311
+    /** the class to place on target elements when htmx is in the settling phase */
312
+    settlingClass?: "htmx-settling" | string;
313
+    /** the class to place on target elements when htmx is in the swapping phase */
314
+    swappingClass?: "htmx-swapping" | string;
315
+    /** allows the use of eval-like functionality in htmx, to enable **hx-vars**, trigger conditions & script tag evaluation. Can be set to **false** for CSP compatibility */
316
+    allowEval?: boolean;
317
+    /** use HTML template tags for parsing content from the server. This allows you to use Out of Band content when returning things like table rows, but it is *not* IE11 compatible. */
318
+    useTemplateFragments?: boolean;
319
+    /** allow cross-site Access-Control requests using credentials such as cookies, authorization headers or TLS client certificates */
320
+    withCredentials?: boolean;
321
+    /** the default implementation of **getWebSocketReconnectDelay** for reconnecting after unexpected connection loss by the event code **Abnormal Closure**, **Service Restart** or **Try Again Later** */
322
+    wsReconnectDelay?: "full-jitter" | string | ((retryCount: number) => number);
323
+    // following don't appear in the docs
324
+    refreshOnHistoryMiss?: boolean;
325
+    timeout?: number;
326
+    disableSelector?: "[hx-disable], [data-hx-disable]" | string;
327
+    scrollBehavior?: "smooth";
328
+}
329
+
330
+/**
331
+ * https://htmx.org/extensions/#defining
332
+ */
333
+export interface HtmxExtension {
334
+    onEvent?: (name: string, evt: CustomEvent) => any;
335
+    transformResponse?: (text: any, xhr: XMLHttpRequest, elt: any) => any;
336
+    isInlineSwap?: (swapStyle: any) => any;
337
+    handleSwap?: (swapStyle: any, target: any, fragment: any, settleInfo: any) => any;
338
+    encodeParameters?: (xhr: XMLHttpRequest, parameters: any, elt: any) => any;
339
+}
0 340
new file mode 100644
... ...
@@ -0,0 +1,3566 @@
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
+            logger : null,
48
+            config : {
49
+                historyEnabled:true,
50
+                historyCacheSize:10,
51
+                refreshOnHistoryMiss:false,
52
+                defaultSwapStyle:'innerHTML',
53
+                defaultSwapDelay:0,
54
+                defaultSettleDelay:20,
55
+                includeIndicatorStyles:true,
56
+                indicatorClass:'htmx-indicator',
57
+                requestClass:'htmx-request',
58
+                addedClass:'htmx-added',
59
+                settlingClass:'htmx-settling',
60
+                swappingClass:'htmx-swapping',
61
+                allowEval:true,
62
+                inlineScriptNonce:'',
63
+                attributesToSettle:["class", "style", "width", "height"],
64
+                withCredentials:false,
65
+                timeout:0,
66
+                wsReconnectDelay: 'full-jitter',
67
+                wsBinaryType: 'blob',
68
+                disableSelector: "[hx-disable], [data-hx-disable]",
69
+                useTemplateFragments: false,
70
+                scrollBehavior: 'smooth',
71
+                defaultFocusScroll: false,
72
+                getCacheBusterParam: false,
73
+                globalViewTransitions: false,
74
+            },
75
+            parseInterval:parseInterval,
76
+            _:internalEval,
77
+            createEventSource: function(url){
78
+                return new EventSource(url, {withCredentials:true})
79
+            },
80
+            createWebSocket: function(url){
81
+                var sock = new WebSocket(url, []);
82
+                sock.binaryType = htmx.config.wsBinaryType;
83
+                return sock;
84
+            },
85
+            version: "1.9.2"
86
+        };
87
+
88
+        /** @type {import("./htmx").HtmxInternalApi} */
89
+        var internalAPI = {
90
+            addTriggerHandler: addTriggerHandler,
91
+            bodyContains: bodyContains,
92
+            canAccessLocalStorage: canAccessLocalStorage,
93
+            filterValues: filterValues,
94
+            hasAttribute: hasAttribute,
95
+            getAttributeValue: getAttributeValue,
96
+            getClosestMatch: getClosestMatch,
97
+            getExpressionVars: getExpressionVars,
98
+            getHeaders: getHeaders,
99
+            getInputValues: getInputValues,
100
+            getInternalData: getInternalData,
101
+            getSwapSpecification: getSwapSpecification,
102
+            getTriggerSpecs: getTriggerSpecs,
103
+            getTarget: getTarget,
104
+            makeFragment: makeFragment,
105
+            mergeObjects: mergeObjects,
106
+            makeSettleInfo: makeSettleInfo,
107
+            oobSwap: oobSwap,
108
+            selectAndSwap: selectAndSwap,
109
+            settleImmediately: settleImmediately,
110
+            shouldCancel: shouldCancel,
111
+            triggerEvent: triggerEvent,
112
+            triggerErrorEvent: triggerErrorEvent,
113
+            withExtensions: withExtensions,
114
+        }
115
+
116
+        var VERBS = ['get', 'post', 'put', 'delete', 'patch'];
117
+        var VERB_SELECTOR = VERBS.map(function(verb){
118
+            return "[hx-" + verb + "], [data-hx-" + verb + "]"
119
+        }).join(", ");
120
+
121
+        //====================================================================
122
+        // Utilities
123
+        //====================================================================
124
+
125
+        function parseInterval(str) {
126
+            if (str == undefined)  {
127
+                return undefined
128
+            }
129
+            if (str.slice(-2) == "ms") {
130
+                return parseFloat(str.slice(0,-2)) || undefined
131
+            }
132
+            if (str.slice(-1) == "s") {
133
+                return (parseFloat(str.slice(0,-1)) * 1000) || undefined
134
+            }
135
+            if (str.slice(-1) == "m") {
136
+                return (parseFloat(str.slice(0,-1)) * 1000 * 60) || undefined
137
+            }
138
+            return parseFloat(str) || undefined
139
+        }
140
+
141
+        /**
142
+         * @param {HTMLElement} elt
143
+         * @param {string} name
144
+         * @returns {(string | null)}
145
+         */
146
+        function getRawAttribute(elt, name) {
147
+            return elt.getAttribute && elt.getAttribute(name);
148
+        }
149
+
150
+        // resolve with both hx and data-hx prefixes
151
+        function hasAttribute(elt, qualifiedName) {
152
+            return elt.hasAttribute && (elt.hasAttribute(qualifiedName) ||
153
+                elt.hasAttribute("data-" + qualifiedName));
154
+        }
155
+
156
+        /**
157
+         *
158
+         * @param {HTMLElement} elt
159
+         * @param {string} qualifiedName
160
+         * @returns {(string | null)}
161
+         */
162
+        function getAttributeValue(elt, qualifiedName) {
163
+            return getRawAttribute(elt, qualifiedName) || getRawAttribute(elt, "data-" + qualifiedName);
164
+        }
165
+
166
+        /**
167
+         * @param {HTMLElement} elt
168
+         * @returns {HTMLElement | null}
169
+         */
170
+        function parentElt(elt) {
171
+            return elt.parentElement;
172
+        }
173
+
174
+        /**
175
+         * @returns {Document}
176
+         */
177
+        function getDocument() {
178
+            return document;
179
+        }
180
+
181
+        /**
182
+         * @param {HTMLElement} elt
183
+         * @param {(e:HTMLElement) => boolean} condition
184
+         * @returns {HTMLElement | null}
185
+         */
186
+        function getClosestMatch(elt, condition) {
187
+            while (elt && !condition(elt)) {
188
+                elt = parentElt(elt);
189
+            }
190
+
191
+            return elt ? elt : null;
192
+        }
193
+
194
+        function getAttributeValueWithDisinheritance(initialElement, ancestor, attributeName){
195
+            var attributeValue = getAttributeValue(ancestor, attributeName);
196
+            var disinherit = getAttributeValue(ancestor, "hx-disinherit");
197
+            if (initialElement !== ancestor && disinherit && (disinherit === "*" || disinherit.split(" ").indexOf(attributeName) >= 0)) {
198
+                return "unset";
199
+            } else {
200
+                return attributeValue
201
+            }
202
+        }
203
+
204
+        /**
205
+         * @param {HTMLElement} elt
206
+         * @param {string} attributeName
207
+         * @returns {string | null}
208
+         */
209
+        function getClosestAttributeValue(elt, attributeName) {
210
+            var closestAttr = null;
211
+            getClosestMatch(elt, function (e) {
212
+                return closestAttr = getAttributeValueWithDisinheritance(elt, e, attributeName);
213
+            });
214
+            if (closestAttr !== "unset") {
215
+                return closestAttr;
216
+            }
217
+        }
218
+
219
+        /**
220
+         * @param {HTMLElement} elt
221
+         * @param {string} selector
222
+         * @returns {boolean}
223
+         */
224
+        function matches(elt, selector) {
225
+            // @ts-ignore: non-standard properties for browser compatability
226
+            // noinspection JSUnresolvedVariable
227
+            var matchesFunction = elt.matches || elt.matchesSelector || elt.msMatchesSelector || elt.mozMatchesSelector || elt.webkitMatchesSelector || elt.oMatchesSelector;
228
+            return matchesFunction && matchesFunction.call(elt, selector);
229
+        }
230
+
231
+        /**
232
+         * @param {string} str
233
+         * @returns {string}
234
+         */
235
+        function getStartTag(str) {
236
+            var tagMatcher = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i
237
+            var match = tagMatcher.exec( str );
238
+            if (match) {
239
+                return match[1].toLowerCase();
240
+            } else {
241
+                return "";
242
+            }
243
+        }
244
+
245
+        /**
246
+         *
247
+         * @param {string} resp
248
+         * @param {number} depth
249
+         * @returns {Element}
250
+         */
251
+        function parseHTML(resp, depth) {
252
+            var parser = new DOMParser();
253
+            var responseDoc = parser.parseFromString(resp, "text/html");
254
+
255
+            /** @type {Element} */
256
+            var responseNode = responseDoc.body;
257
+            while (depth > 0) {
258
+                depth--;
259
+                // @ts-ignore
260
+                responseNode = responseNode.firstChild;
261
+            }
262
+            if (responseNode == null) {
263
+                // @ts-ignore
264
+                responseNode = getDocument().createDocumentFragment();
265
+            }
266
+            return responseNode;
267
+        }
268
+
269
+        function aFullPageResponse(resp) {
270
+            return resp.match(/<body/);
271
+        }
272
+
273
+        /**
274
+         *
275
+         * @param {string} resp
276
+         * @returns {Element}
277
+         */
278
+        function makeFragment(resp) {
279
+            var partialResponse = !aFullPageResponse(resp);
280
+            if (htmx.config.useTemplateFragments && partialResponse) {
281
+                var documentFragment = parseHTML("<body><template>" + resp + "</template></body>", 0);
282
+                // @ts-ignore type mismatch between DocumentFragment and Element.
283
+                // TODO: Are these close enough for htmx to use interchangably?
284
+                return documentFragment.querySelector('template').content;
285
+            } else {
286
+                var startTag = getStartTag(resp);
287
+                switch (startTag) {
288
+                    case "thead":
289
+                    case "tbody":
290
+                    case "tfoot":
291
+                    case "colgroup":
292
+                    case "caption":
293
+                        return parseHTML("<table>" + resp + "</table>", 1);
294
+                    case "col":
295
+                        return parseHTML("<table><colgroup>" + resp + "</colgroup></table>", 2);
296
+                    case "tr":
297
+                        return parseHTML("<table><tbody>" + resp + "</tbody></table>", 2);
298
+                    case "td":
299
+                    case "th":
300
+                        return parseHTML("<table><tbody><tr>" + resp + "</tr></tbody></table>", 3);
301
+                    case "script":
302
+                        return parseHTML("<div>" + resp + "</div>", 1);
303
+                    default:
304
+                        return parseHTML(resp, 0);
305
+                }
306
+            }
307
+        }
308
+
309
+        /**
310
+         * @param {Function} func
311
+         */
312
+        function maybeCall(func){
313
+            if(func) {
314
+                func();
315
+            }
316
+        }
317
+
318
+        /**
319
+         * @param {any} o
320
+         * @param {string} type
321
+         * @returns
322
+         */
323
+        function isType(o, type) {
324
+            return Object.prototype.toString.call(o) === "[object " + type + "]";
325
+        }
326
+
327
+        /**
328
+         * @param {*} o
329
+         * @returns {o is Function}
330
+         */
331
+        function isFunction(o) {
332
+            return isType(o, "Function");
333
+        }
334
+
335
+        /**
336
+         * @param {*} o
337
+         * @returns {o is Object}
338
+         */
339
+        function isRawObject(o) {
340
+            return isType(o, "Object");
341
+        }
342
+
343
+        /**
344
+         * getInternalData retrieves "private" data stored by htmx within an element
345
+         * @param {HTMLElement} elt
346
+         * @returns {*}
347
+         */
348
+        function getInternalData(elt) {
349
+            var dataProp = 'htmx-internal-data';
350
+            var data = elt[dataProp];
351
+            if (!data) {
352
+                data = elt[dataProp] = {};
353
+            }
354
+            return data;
355
+        }
356
+
357
+        /**
358
+         * toArray converts an ArrayLike object into a real array.
359
+         * @param {ArrayLike} arr
360
+         * @returns {any[]}
361
+         */
362
+        function toArray(arr) {
363
+            var returnArr = [];
364
+            if (arr) {
365
+                for (var i = 0; i < arr.length; i++) {
366
+                    returnArr.push(arr[i]);
367
+                }
368
+            }
369
+            return returnArr
370
+        }
371
+
372
+        function forEach(arr, func) {
373
+            if (arr) {
374
+                for (var i = 0; i < arr.length; i++) {
375
+                    func(arr[i]);
376
+                }
377
+            }
378
+        }
379
+
380
+        function isScrolledIntoView(el) {
381
+            var rect = el.getBoundingClientRect();
382
+            var elemTop = rect.top;
383
+            var elemBottom = rect.bottom;
384
+            return elemTop < window.innerHeight && elemBottom >= 0;
385
+        }
386
+
387
+        function bodyContains(elt) {
388
+            // IE Fix
389
+            if (elt.getRootNode && elt.getRootNode() instanceof ShadowRoot) {
390
+                return getDocument().body.contains(elt.getRootNode().host);
391
+            } else {
392
+                return getDocument().body.contains(elt);
393
+            }
394
+        }
395
+
396
+        function splitOnWhitespace(trigger) {
397
+            return trigger.trim().split(/\s+/);
398
+        }
399
+
400
+        /**
401
+         * mergeObjects takes all of the keys from
402
+         * obj2 and duplicates them into obj1
403
+         * @param {Object} obj1
404
+         * @param {Object} obj2
405
+         * @returns {Object}
406
+         */
407
+        function mergeObjects(obj1, obj2) {
408
+            for (var key in obj2) {
409
+                if (obj2.hasOwnProperty(key)) {
410
+                    obj1[key] = obj2[key];
411
+                }
412
+            }
413
+            return obj1;
414
+        }
415
+
416
+        function parseJSON(jString) {
417
+            try {
418
+                return JSON.parse(jString);
419
+            } catch(error) {
420
+                logError(error);
421
+                return null;
422
+            }
423
+        }
424
+
425
+        function canAccessLocalStorage() {
426
+            var test = 'htmx:localStorageTest';
427
+            try {
428
+                localStorage.setItem(test, test);
429
+                localStorage.removeItem(test);
430
+                return true;
431
+            } catch(e) {
432
+                return false;
433
+            }
434
+        }
435
+
436
+        function normalizePath(path) {
437
+            try {
438
+                var url = new URL(path);
439
+                if (url) {
440
+                    path = url.pathname + url.search;
441
+                }
442
+                // remove trailing slash, unless index page
443
+                if (!path.match('^/$')) {
444
+                    path = path.replace(/\/+$/, '');
445
+                }
446
+                return path;
447
+            } catch (e) {
448
+                // be kind to IE11, which doesn't support URL()
449
+                return path;
450
+            }
451
+        }
452
+
453
+        //==========================================================================================
454
+        // public API
455
+        //==========================================================================================
456
+
457
+        function internalEval(str){
458
+            return maybeEval(getDocument().body, function () {
459
+                return eval(str);
460
+            });
461
+        }
462
+
463
+        function onLoadHelper(callback) {
464
+            var value = htmx.on("htmx:load", function(evt) {
465
+                callback(evt.detail.elt);
466
+            });
467
+            return value;
468
+        }
469
+
470
+        function logAll(){
471
+            htmx.logger = function(elt, event, data) {
472
+                if(console) {
473
+                    console.log(event, elt, data);
474
+                }
475
+            }
476
+        }
477
+
478
+        function find(eltOrSelector, selector) {
479
+            if (selector) {
480
+                return eltOrSelector.querySelector(selector);
481
+            } else {
482
+                return find(getDocument(), eltOrSelector);
483
+            }
484
+        }
485
+
486
+        function findAll(eltOrSelector, selector) {
487
+            if (selector) {
488
+                return eltOrSelector.querySelectorAll(selector);
489
+            } else {
490
+                return findAll(getDocument(), eltOrSelector);
491
+            }
492
+        }
493
+
494
+        function removeElement(elt, delay) {
495
+            elt = resolveTarget(elt);
496
+            if (delay) {
497
+                setTimeout(function(){
498
+                    removeElement(elt);
499
+                    elt = null;
500
+                }, delay);
501
+            } else {
502
+                elt.parentElement.removeChild(elt);
503
+            }
504
+        }
505
+
506
+        function addClassToElement(elt, clazz, delay) {
507
+            elt = resolveTarget(elt);
508
+            if (delay) {
509
+                setTimeout(function(){
510
+                    addClassToElement(elt, clazz);
511
+                    elt = null;
512
+                }, delay);
513
+            } else {
514
+                elt.classList && elt.classList.add(clazz);
515
+            }
516
+        }
517
+
518
+        function removeClassFromElement(elt, clazz, delay) {
519
+            elt = resolveTarget(elt);
520
+            if (delay) {
521
+                setTimeout(function(){
522
+                    removeClassFromElement(elt, clazz);
523
+                    elt = null;
524
+                }, delay);
525
+            } else {
526
+                if (elt.classList) {
527
+                    elt.classList.remove(clazz);
528
+                    // if there are no classes left, remove the class attribute
529
+                    if (elt.classList.length === 0) {
530
+                        elt.removeAttribute("class");
531
+                    }
532
+                }
533
+            }
534
+        }
535
+
536
+        function toggleClassOnElement(elt, clazz) {
537
+            elt = resolveTarget(elt);
538
+            elt.classList.toggle(clazz);
539
+        }
540
+
541
+        function takeClassForElement(elt, clazz) {
542
+            elt = resolveTarget(elt);
543
+            forEach(elt.parentElement.children, function(child){
544
+                removeClassFromElement(child, clazz);
545
+            })
546
+            addClassToElement(elt, clazz);
547
+        }
548
+
549
+        function closest(elt, selector) {
550
+            elt = resolveTarget(elt);
551
+            if (elt.closest) {
552
+                return elt.closest(selector);
553
+            } else {
554
+                // TODO remove when IE goes away
555
+                do{
556
+                    if (elt == null || matches(elt, selector)){
557
+                        return elt;
558
+                    }
559
+                }
560
+                while (elt = elt && parentElt(elt));
561
+                return null;
562
+            }
563
+        }
564
+
565
+        function normalizeSelector(selector) {
566
+            var trimmedSelector = selector.trim();
567
+            if (trimmedSelector.startsWith("<") && trimmedSelector.endsWith("/>")) {
568
+                return trimmedSelector.substring(1, trimmedSelector.length - 2);
569
+            } else {
570
+                return trimmedSelector;
571
+            }
572
+        }
573
+
574
+        function querySelectorAllExt(elt, selector) {
575
+            if (selector.indexOf("closest ") === 0) {
576
+                return [closest(elt, normalizeSelector(selector.substr(8)))];
577
+            } else if (selector.indexOf("find ") === 0) {
578
+                return [find(elt, normalizeSelector(selector.substr(5)))];
579
+            } else if (selector.indexOf("next ") === 0) {
580
+                return [scanForwardQuery(elt, normalizeSelector(selector.substr(5)))];
581
+            } else if (selector.indexOf("previous ") === 0) {
582
+                return [scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)))];
583
+            } else if (selector === 'document') {
584
+                return [document];
585
+            } else if (selector === 'window') {
586
+                return [window];
587
+            } else {
588
+                return getDocument().querySelectorAll(normalizeSelector(selector));
589
+            }
590
+        }
591
+
592
+        var scanForwardQuery = function(start, match) {
593
+            var results = getDocument().querySelectorAll(match);
594
+            for (var i = 0; i < results.length; i++) {
595
+                var elt = results[i];
596
+                if (elt.compareDocumentPosition(start) === Node.DOCUMENT_POSITION_PRECEDING) {
597
+                    return elt;
598
+                }
599
+            }
600
+        }
601
+
602
+        var scanBackwardsQuery = function(start, match) {
603
+            var results = getDocument().querySelectorAll(match);
604
+            for (var i = results.length - 1; i >= 0; i--) {
605
+                var elt = results[i];
606
+                if (elt.compareDocumentPosition(start) === Node.DOCUMENT_POSITION_FOLLOWING) {
607
+                    return elt;
608
+                }
609
+            }
610
+        }
611
+
612
+        function querySelectorExt(eltOrSelector, selector) {
613
+            if (selector) {
614
+                return querySelectorAllExt(eltOrSelector, selector)[0];
615
+            } else {
616
+                return querySelectorAllExt(getDocument().body, eltOrSelector)[0];
617
+            }
618
+        }
619
+
620
+        function resolveTarget(arg2) {
621
+            if (isType(arg2, 'String')) {
622
+                return find(arg2);
623
+            } else {
624
+                return arg2;
625
+            }
626
+        }
627
+
628
+        function processEventArgs(arg1, arg2, arg3) {
629
+            if (isFunction(arg2)) {
630
+                return {
631
+                    target: getDocument().body,
632
+                    event: arg1,
633
+                    listener: arg2
634
+                }
635
+            } else {
636
+                return {
637
+                    target: resolveTarget(arg1),
638
+                    event: arg2,
639
+                    listener: arg3
640
+                }
641
+            }
642
+
643
+        }
644
+
645
+        function addEventListenerImpl(arg1, arg2, arg3) {
646
+            ready(function(){
647
+                var eventArgs = processEventArgs(arg1, arg2, arg3);
648
+                eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener);
649
+            })
650
+            var b = isFunction(arg2);
651
+            return b ? arg2 : arg3;
652
+        }
653
+
654
+        function removeEventListenerImpl(arg1, arg2, arg3) {
655
+            ready(function(){
656
+                var eventArgs = processEventArgs(arg1, arg2, arg3);
657
+                eventArgs.target.removeEventListener(eventArgs.event, eventArgs.listener);
658
+            })
659
+            return isFunction(arg2) ? arg2 : arg3;
660
+        }
661
+
662
+        //====================================================================
663
+        // Node processing
664
+        //====================================================================
665
+
666
+        var DUMMY_ELT = getDocument().createElement("output"); // dummy element for bad selectors
667
+        function findAttributeTargets(elt, attrName) {
668
+            var attrTarget = getClosestAttributeValue(elt, attrName);
669
+            if (attrTarget) {
670
+                if (attrTarget === "this") {
671
+                    return [findThisElement(elt, attrName)];
672
+                } else {
673
+                    var result = querySelectorAllExt(elt, attrTarget);
674
+                    if (result.length === 0) {
675
+                        logError('The selector "' + attrTarget + '" on ' + attrName + " returned no matches!");
676
+                        return [DUMMY_ELT]
677
+                    } else {
678
+                        return result;
679
+                    }
680
+                }
681
+            }
682
+        }
683
+
684
+        function findThisElement(elt, attribute){
685
+            return getClosestMatch(elt, function (elt) {
686
+                return getAttributeValue(elt, attribute) != null;
687
+            })
688
+        }
689
+
690
+        function getTarget(elt) {
691
+            var targetStr = getClosestAttributeValue(elt, "hx-target");
692
+            if (targetStr) {
693
+                if (targetStr === "this") {
694
+                    return findThisElement(elt,'hx-target');
695
+                } else {
696
+                    return querySelectorExt(elt, targetStr)
697
+                }
698
+            } else {
699
+                var data = getInternalData(elt);
700
+                if (data.boosted) {
701
+                    return getDocument().body;
702
+                } else {
703
+                    return elt;
704
+                }
705
+            }
706
+        }
707
+
708
+        function shouldSettleAttribute(name) {
709
+            var attributesToSettle = htmx.config.attributesToSettle;
710
+            for (var i = 0; i < attributesToSettle.length; i++) {
711
+                if (name === attributesToSettle[i]) {
712
+                    return true;
713
+                }
714
+            }
715
+            return false;
716
+        }
717
+
718
+        function cloneAttributes(mergeTo, mergeFrom) {
719
+            forEach(mergeTo.attributes, function (attr) {
720
+                if (!mergeFrom.hasAttribute(attr.name) && shouldSettleAttribute(attr.name)) {
721
+                    mergeTo.removeAttribute(attr.name)
722
+                }
723
+            });
724
+            forEach(mergeFrom.attributes, function (attr) {
725
+                if (shouldSettleAttribute(attr.name)) {
726
+                    mergeTo.setAttribute(attr.name, attr.value);
727
+                }
728
+            });
729
+        }
730
+
731
+        function isInlineSwap(swapStyle, target) {
732
+            var extensions = getExtensions(target);
733
+            for (var i = 0; i < extensions.length; i++) {
734
+                var extension = extensions[i];
735
+                try {
736
+                    if (extension.isInlineSwap(swapStyle)) {
737
+                        return true;
738
+                    }
739
+                } catch(e) {
740
+                    logError(e);
741
+                }
742
+            }
743
+            return swapStyle === "outerHTML";
744
+        }
745
+
746
+        /**
747
+         *
748
+         * @param {string} oobValue
749
+         * @param {HTMLElement} oobElement
750
+         * @param {*} settleInfo
751
+         * @returns
752
+         */
753
+        function oobSwap(oobValue, oobElement, settleInfo) {
754
+            var selector = "#" + oobElement.id;
755
+            var swapStyle = "outerHTML";
756
+            if (oobValue === "true") {
757
+                // do nothing
758
+            } else if (oobValue.indexOf(":") > 0) {
759
+                swapStyle = oobValue.substr(0, oobValue.indexOf(":"));
760
+                selector  = oobValue.substr(oobValue.indexOf(":") + 1, oobValue.length);
761
+            } else {
762
+                swapStyle = oobValue;
763
+            }
764
+
765
+            var targets = getDocument().querySelectorAll(selector);
766
+            if (targets) {
767
+                forEach(
768
+                    targets,
769
+                    function (target) {
770
+                        var fragment;
771
+                        var oobElementClone = oobElement.cloneNode(true);
772
+                        fragment = getDocument().createDocumentFragment();
773
+                        fragment.appendChild(oobElementClone);
774
+                        if (!isInlineSwap(swapStyle, target)) {
775
+                            fragment = oobElementClone; // if this is not an inline swap, we use the content of the node, not the node itself
776
+                        }
777
+
778
+                        var beforeSwapDetails = {shouldSwap: true, target: target, fragment:fragment };
779
+                        if (!triggerEvent(target, 'htmx:oobBeforeSwap', beforeSwapDetails)) return;
780
+
781
+                        target = beforeSwapDetails.target; // allow re-targeting
782
+                        if (beforeSwapDetails['shouldSwap']){
783
+                            swap(swapStyle, target, target, fragment, settleInfo);
784
+                        }
785
+                        forEach(settleInfo.elts, function (elt) {
786
+                            triggerEvent(elt, 'htmx:oobAfterSwap', beforeSwapDetails);
787
+                        });
788
+                    }
789
+                );
790
+                oobElement.parentNode.removeChild(oobElement);
791
+            } else {
792
+                oobElement.parentNode.removeChild(oobElement);
793
+                triggerErrorEvent(getDocument().body, "htmx:oobErrorNoTarget", {content: oobElement});
794
+            }
795
+            return oobValue;
796
+        }
797
+
798
+        function handleOutOfBandSwaps(elt, fragment, settleInfo) {
799
+            var oobSelects = getClosestAttributeValue(elt, "hx-select-oob");
800
+            if (oobSelects) {
801
+                var oobSelectValues = oobSelects.split(",");
802
+                for (let i = 0; i < oobSelectValues.length; i++) {
803
+                    var oobSelectValue = oobSelectValues[i].split(":", 2);
804
+                    var id = oobSelectValue[0].trim();
805
+                    if (id.indexOf("#") === 0) {
806
+                        id = id.substring(1);
807
+                    }
808
+                    var oobValue = oobSelectValue[1] || "true";
809
+                    var oobElement = fragment.querySelector("#" + id);
810
+                    if (oobElement) {
811
+                        oobSwap(oobValue, oobElement, settleInfo);
812
+                    }
813
+                }
814
+            }
815
+            forEach(findAll(fragment, '[hx-swap-oob], [data-hx-swap-oob]'), function (oobElement) {
816
+                var oobValue = getAttributeValue(oobElement, "hx-swap-oob");
817
+                if (oobValue != null) {
818
+                    oobSwap(oobValue, oobElement, settleInfo);
819
+                }
820
+            });
821
+        }
822
+
823
+        function handlePreservedElements(fragment) {
824
+            forEach(findAll(fragment, '[hx-preserve], [data-hx-preserve]'), function (preservedElt) {
825
+                var id = getAttributeValue(preservedElt, "id");
826
+                var oldElt = getDocument().getElementById(id);
827
+                if (oldElt != null) {
828
+                    preservedElt.parentNode.replaceChild(oldElt, preservedElt);
829
+                }
830
+            });
831
+        }
832
+
833
+        function handleAttributes(parentNode, fragment, settleInfo) {
834
+            forEach(fragment.querySelectorAll("[id]"), function (newNode) {
835
+                if (newNode.id && newNode.id.length > 0) {
836
+                    var normalizedId = newNode.id.replace("'", "\\'");
837
+                    var normalizedTag = newNode.tagName.replace(':', '\\:');
838
+                    var oldNode = parentNode.querySelector(normalizedTag + "[id='" + normalizedId + "']");
839
+                    if (oldNode && oldNode !== parentNode) {
840
+                        var newAttributes = newNode.cloneNode();
841
+                        cloneAttributes(newNode, oldNode);
842
+                        settleInfo.tasks.push(function () {
843
+                            cloneAttributes(newNode, newAttributes);
844
+                        });
845
+                    }
846
+                }
847
+            });
848
+        }
849
+
850
+        function makeAjaxLoadTask(child) {
851
+            return function () {
852
+                removeClassFromElement(child, htmx.config.addedClass);
853
+                processNode(child);
854
+                processScripts(child);
855
+                processFocus(child)
856
+                triggerEvent(child, 'htmx:load');
857
+            };
858
+        }
859
+
860
+        function processFocus(child) {
861
+            var autofocus = "[autofocus]";
862
+            var autoFocusedElt = matches(child, autofocus) ? child : child.querySelector(autofocus)
863
+            if (autoFocusedElt != null) {
864
+                autoFocusedElt.focus();
865
+            }
866
+        }
867
+
868
+        function insertNodesBefore(parentNode, insertBefore, fragment, settleInfo) {
869
+            handleAttributes(parentNode, fragment, settleInfo);
870
+            while(fragment.childNodes.length > 0){
871
+                var child = fragment.firstChild;
872
+                addClassToElement(child, htmx.config.addedClass);
873
+                parentNode.insertBefore(child, insertBefore);
874
+                if (child.nodeType !== Node.TEXT_NODE && child.nodeType !== Node.COMMENT_NODE) {
875
+                    settleInfo.tasks.push(makeAjaxLoadTask(child));
876
+                }
877
+            }
878
+        }
879
+
880
+        // based on https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0,
881
+        // derived from Java's string hashcode implementation
882
+        function stringHash(string, hash) {
883
+            var char = 0;
884
+            while (char < string.length){
885
+                hash = (hash << 5) - hash + string.charCodeAt(char++) | 0; // bitwise or ensures we have a 32-bit int
886
+            }
887
+            return hash;
888
+        }
889
+
890
+        function attributeHash(elt) {
891
+            var hash = 0;
892
+            // IE fix
893
+            if (elt.attributes) {
894
+                for (var i = 0; i < elt.attributes.length; i++) {
895
+                    var attribute = elt.attributes[i];
896
+                    if(attribute.value){ // only include attributes w/ actual values (empty is same as non-existent)
897
+                        hash = stringHash(attribute.name, hash);
898
+                        hash = stringHash(attribute.value, hash);
899
+                    }
900
+                }
901
+            }
902
+            return hash;
903
+        }
904
+
905
+        function deInitNode(element) {
906
+            var internalData = getInternalData(element);
907
+            if (internalData.timeout) {
908
+                clearTimeout(internalData.timeout);
909
+            }
910
+            if (internalData.webSocket) {
911
+                internalData.webSocket.close();
912
+            }
913
+            if (internalData.sseEventSource) {
914
+                internalData.sseEventSource.close();
915
+            }
916
+            if (internalData.listenerInfos) {
917
+                forEach(internalData.listenerInfos, function (info) {
918
+                    if (info.on) {
919
+                        info.on.removeEventListener(info.trigger, info.listener);
920
+                    }
921
+                });
922
+            }
923
+            if (internalData.onHandlers) {
924
+                for (let i = 0; i < internalData.onHandlers.length; i++) {
925
+                    const handlerInfo = internalData.onHandlers[i];
926
+                    element.removeEventListener(handlerInfo.name, handlerInfo.handler);
927
+                }
928
+            }
929
+        }
930
+
931
+        function cleanUpElement(element) {
932
+            triggerEvent(element, "htmx:beforeCleanupElement")
933
+            deInitNode(element);
934
+            if (element.children) { // IE
935
+                forEach(element.children, function(child) { cleanUpElement(child) });
936
+            }
937
+        }
938
+
939
+        function swapOuterHTML(target, fragment, settleInfo) {
940
+            if (target.tagName === "BODY") {
941
+                return swapInnerHTML(target, fragment, settleInfo);
942
+            } else {
943
+                // @type {HTMLElement}
944
+                var newElt
945
+                var eltBeforeNewContent = target.previousSibling;
946
+                insertNodesBefore(parentElt(target), target, fragment, settleInfo);
947
+                if (eltBeforeNewContent == null) {
948
+                    newElt = parentElt(target).firstChild;
949
+                } else {
950
+                    newElt = eltBeforeNewContent.nextSibling;
951
+                }
952
+                getInternalData(target).replacedWith = newElt; // tuck away so we can fire events on it later
953
+                settleInfo.elts = [] // clear existing elements
954
+                while(newElt && newElt !== target) {
955
+                    if (newElt.nodeType === Node.ELEMENT_NODE) {
956
+                        settleInfo.elts.push(newElt);
957
+                    }
958
+                    newElt = newElt.nextElementSibling;
959
+                }
960
+                cleanUpElement(target);
961
+                parentElt(target).removeChild(target);
962
+            }
963
+        }
964
+
965
+        function swapAfterBegin(target, fragment, settleInfo) {
966
+            return insertNodesBefore(target, target.firstChild, fragment, settleInfo);
967
+        }
968
+
969
+        function swapBeforeBegin(target, fragment, settleInfo) {
970
+            return insertNodesBefore(parentElt(target), target, fragment, settleInfo);
971
+        }
972
+
973
+        function swapBeforeEnd(target, fragment, settleInfo) {
974
+            return insertNodesBefore(target, null, fragment, settleInfo);
975
+        }
976
+
977
+        function swapAfterEnd(target, fragment, settleInfo) {
978
+            return insertNodesBefore(parentElt(target), target.nextSibling, fragment, settleInfo);
979
+        }
980
+        function swapDelete(target, fragment, settleInfo) {
981
+            cleanUpElement(target);
982
+            return parentElt(target).removeChild(target);
983
+        }
984
+
985
+        function swapInnerHTML(target, fragment, settleInfo) {
986
+            var firstChild = target.firstChild;
987
+            insertNodesBefore(target, firstChild, fragment, settleInfo);
988
+            if (firstChild) {
989
+                while (firstChild.nextSibling) {
990
+                    cleanUpElement(firstChild.nextSibling)
991
+                    target.removeChild(firstChild.nextSibling);
992
+                }
993
+                cleanUpElement(firstChild)
994
+                target.removeChild(firstChild);
995
+            }
996
+        }
997
+
998
+        function maybeSelectFromResponse(elt, fragment) {
999
+            var selector = getClosestAttributeValue(elt, "hx-select");
1000
+            if (selector) {
1001
+                var newFragment = getDocument().createDocumentFragment();
1002
+                forEach(fragment.querySelectorAll(selector), function (node) {
1003
+                    newFragment.appendChild(node);
1004
+                });
1005
+                fragment = newFragment;
1006
+            }
1007
+            return fragment;
1008
+        }
1009
+
1010
+        function swap(swapStyle, elt, target, fragment, settleInfo) {
1011
+            switch (swapStyle) {
1012
+                case "none":
1013
+                    return;
1014
+                case "outerHTML":
1015
+                    swapOuterHTML(target, fragment, settleInfo);
1016
+                    return;
1017
+                case "afterbegin":
1018
+                    swapAfterBegin(target, fragment, settleInfo);
1019
+                    return;
1020
+                case "beforebegin":
1021
+                    swapBeforeBegin(target, fragment, settleInfo);
1022
+                    return;
1023
+                case "beforeend":
1024
+                    swapBeforeEnd(target, fragment, settleInfo);
1025
+                    return;
1026
+                case "afterend":
1027
+                    swapAfterEnd(target, fragment, settleInfo);
1028
+                    return;
1029
+                case "delete":
1030
+                    swapDelete(target, fragment, settleInfo);
1031
+                    return;
1032
+                default:
1033
+                    var extensions = getExtensions(elt);
1034
+                    for (var i = 0; i < extensions.length; i++) {
1035
+                        var ext = extensions[i];
1036
+                        try {
1037
+                            var newElements = ext.handleSwap(swapStyle, target, fragment, settleInfo);
1038
+                            if (newElements) {
1039
+                                if (typeof newElements.length !== 'undefined') {
1040
+                                    // if handleSwap returns an array (like) of elements, we handle them
1041
+                                    for (var j = 0; j < newElements.length; j++) {
1042
+                                        var child = newElements[j];
1043
+                                        if (child.nodeType !== Node.TEXT_NODE && child.nodeType !== Node.COMMENT_NODE) {
1044
+                                            settleInfo.tasks.push(makeAjaxLoadTask(child));
1045
+                                        }
1046
+                                    }
1047
+                                }
1048
+                                return;
1049
+                            }
1050
+                        } catch (e) {
1051
+                            logError(e);
1052
+                        }
1053
+                    }
1054
+                    if (swapStyle === "innerHTML") {
1055
+                        swapInnerHTML(target, fragment, settleInfo);
1056
+                    } else {
1057
+                        swap(htmx.config.defaultSwapStyle, elt, target, fragment, settleInfo);
1058
+                    }
1059
+            }
1060
+        }
1061
+
1062
+        function findTitle(content) {
1063
+            if (content.indexOf('<title') > -1) {
1064
+                var contentWithSvgsRemoved = content.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim, '');
1065
+                var result = contentWithSvgsRemoved.match(/<title(\s[^>]*>|>)([\s\S]*?)<\/title>/im);
1066
+
1067
+                if (result) {
1068
+                    return result[2];
1069
+                }
1070
+            }
1071
+        }
1072
+
1073
+        function selectAndSwap(swapStyle, target, elt, responseText, settleInfo) {
1074
+            settleInfo.title = findTitle(responseText);
1075
+            var fragment = makeFragment(responseText);
1076
+            if (fragment) {
1077
+                handleOutOfBandSwaps(elt, fragment, settleInfo);
1078
+                fragment = maybeSelectFromResponse(elt, fragment);
1079
+                handlePreservedElements(fragment);
1080
+                return swap(swapStyle, elt, target, fragment, settleInfo);
1081
+            }
1082
+        }
1083
+
1084
+        function handleTrigger(xhr, header, elt) {
1085
+            var triggerBody = xhr.getResponseHeader(header);
1086
+            if (triggerBody.indexOf("{") === 0) {
1087
+                var triggers = parseJSON(triggerBody);
1088
+                for (var eventName in triggers) {
1089
+                    if (triggers.hasOwnProperty(eventName)) {
1090
+                        var detail = triggers[eventName];
1091
+                        if (!isRawObject(detail)) {
1092
+                            detail = {"value": detail}
1093
+                        }
1094
+                        triggerEvent(elt, eventName, detail);
1095
+                    }
1096
+                }
1097
+            } else {
1098
+                triggerEvent(elt, triggerBody, []);
1099
+            }
1100
+        }
1101
+
1102
+        var WHITESPACE = /\s/;
1103
+        var WHITESPACE_OR_COMMA = /[\s,]/;
1104
+        var SYMBOL_START = /[_$a-zA-Z]/;
1105
+        var SYMBOL_CONT = /[_$a-zA-Z0-9]/;
1106
+        var STRINGISH_START = ['"', "'", "/"];
1107
+        var NOT_WHITESPACE = /[^\s]/;
1108
+        function tokenizeString(str) {
1109
+            var tokens = [];
1110
+            var position = 0;
1111
+            while (position < str.length) {
1112
+                if(SYMBOL_START.exec(str.charAt(position))) {
1113
+                    var startPosition = position;
1114
+                    while (SYMBOL_CONT.exec(str.charAt(position + 1))) {
1115
+                        position++;
1116
+                    }
1117
+                    tokens.push(str.substr(startPosition, position - startPosition + 1));
1118
+                } else if (STRINGISH_START.indexOf(str.charAt(position)) !== -1) {
1119
+                    var startChar = str.charAt(position);
1120
+                    var startPosition = position;
1121
+                    position++;
1122
+                    while (position < str.length && str.charAt(position) !== startChar ) {
1123
+                        if (str.charAt(position) === "\\") {
1124
+                            position++;
1125
+                        }
1126
+                        position++;
1127
+                    }
1128
+                    tokens.push(str.substr(startPosition, position - startPosition + 1));
1129
+                } else {
1130
+                    var symbol = str.charAt(position);
1131
+                    tokens.push(symbol);
1132
+                }
1133
+                position++;
1134
+            }
1135
+            return tokens;
1136
+        }
1137
+
1138
+        function isPossibleRelativeReference(token, last, paramName) {
1139
+            return SYMBOL_START.exec(token.charAt(0)) &&
1140
+                token !== "true" &&
1141
+                token !== "false" &&
1142
+                token !== "this" &&
1143
+                token !== paramName &&
1144
+                last !== ".";
1145
+        }
1146
+
1147
+        function maybeGenerateConditional(elt, tokens, paramName) {
1148
+            if (tokens[0] === '[') {
1149
+                tokens.shift();
1150
+                var bracketCount = 1;
1151
+                var conditionalSource = " return (function(" + paramName + "){ return (";
1152
+                var last = null;
1153
+                while (tokens.length > 0) {
1154
+                    var token = tokens[0];
1155
+                    if (token === "]") {
1156
+                        bracketCount--;
1157
+                        if (bracketCount === 0) {
1158
+                            if (last === null) {
1159
+                                conditionalSource = conditionalSource + "true";
1160
+                            }
1161
+                            tokens.shift();
1162
+                            conditionalSource += ")})";
1163
+                            try {
1164
+                                var conditionFunction = maybeEval(elt,function () {
1165
+                                    return Function(conditionalSource)();
1166
+                                    },
1167
+                                    function(){return true})
1168
+                                conditionFunction.source = conditionalSource;
1169
+                                return conditionFunction;
1170
+                            } catch (e) {
1171
+                                triggerErrorEvent(getDocument().body, "htmx:syntax:error", {error:e, source:conditionalSource})
1172
+                                return null;
1173
+                            }
1174
+                        }
1175
+                    } else if (token === "[") {
1176
+                        bracketCount++;
1177
+                    }
1178
+                    if (isPossibleRelativeReference(token, last, paramName)) {
1179
+                            conditionalSource += "((" + paramName + "." + token + ") ? (" + paramName + "." + token + ") : (window." + token + "))";
1180
+                    } else {
1181
+                        conditionalSource = conditionalSource + token;
1182
+                    }
1183
+                    last = tokens.shift();
1184
+                }
1185
+            }
1186
+        }
1187
+
1188
+        function consumeUntil(tokens, match) {
1189
+            var result = "";
1190
+            while (tokens.length > 0 && !tokens[0].match(match)) {
1191
+                result += tokens.shift();
1192
+            }
1193
+            return result;
1194
+        }
1195
+
1196
+        var INPUT_SELECTOR = 'input, textarea, select';
1197
+
1198
+        /**
1199
+         * @param {HTMLElement} elt
1200
+         * @returns {import("./htmx").HtmxTriggerSpecification[]}
1201
+         */
1202
+        function getTriggerSpecs(elt) {
1203
+            var explicitTrigger = getAttributeValue(elt, 'hx-trigger');
1204
+            var triggerSpecs = [];
1205
+            if (explicitTrigger) {
1206
+                var tokens = tokenizeString(explicitTrigger);
1207
+                do {
1208
+                    consumeUntil(tokens, NOT_WHITESPACE);
1209
+                    var initialLength = tokens.length;
1210
+                    var trigger = consumeUntil(tokens, /[,\[\s]/);
1211
+                    if (trigger !== "") {
1212
+                        if (trigger === "every") {
1213
+                            var every = {trigger: 'every'};
1214
+                            consumeUntil(tokens, NOT_WHITESPACE);
1215
+                            every.pollInterval = parseInterval(consumeUntil(tokens, /[,\[\s]/));
1216
+                            consumeUntil(tokens, NOT_WHITESPACE);
1217
+                            var eventFilter = maybeGenerateConditional(elt, tokens, "event");
1218
+                            if (eventFilter) {
1219
+                                every.eventFilter = eventFilter;
1220
+                            }
1221
+                            triggerSpecs.push(every);
1222
+                        } else if (trigger.indexOf("sse:") === 0) {
1223
+                            triggerSpecs.push({trigger: 'sse', sseEvent: trigger.substr(4)});
1224
+                        } else {
1225
+                            var triggerSpec = {trigger: trigger};
1226
+                            var eventFilter = maybeGenerateConditional(elt, tokens, "event");
1227
+                            if (eventFilter) {
1228
+                                triggerSpec.eventFilter = eventFilter;
1229
+                            }
1230
+                            while (tokens.length > 0 && tokens[0] !== ",") {
1231
+                                consumeUntil(tokens, NOT_WHITESPACE)
1232
+                                var token = tokens.shift();
1233
+                                if (token === "changed") {
1234
+                                    triggerSpec.changed = true;
1235
+                                } else if (token === "once") {
1236
+                                    triggerSpec.once = true;
1237
+                                } else if (token === "consume") {
1238
+                                    triggerSpec.consume = true;
1239
+                                } else if (token === "delay" && tokens[0] === ":") {
1240
+                                    tokens.shift();
1241
+                                    triggerSpec.delay = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA));
1242
+                                } else if (token === "from" && tokens[0] === ":") {
1243
+                                    tokens.shift();
1244
+                                    var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA);
1245
+                                    if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") {
1246
+                                        tokens.shift();
1247
+                                        from_arg +=
1248
+                                            " " +
1249
+                                            consumeUntil(
1250
+                                                tokens,
1251
+                                                WHITESPACE_OR_COMMA
1252
+                                            );
1253
+                                    }
1254
+                                    triggerSpec.from = from_arg;
1255
+                                } else if (token === "target" && tokens[0] === ":") {
1256
+                                    tokens.shift();
1257
+                                    triggerSpec.target = consumeUntil(tokens, WHITESPACE_OR_COMMA);
1258
+                                } else if (token === "throttle" && tokens[0] === ":") {
1259
+                                    tokens.shift();
1260
+                                    triggerSpec.throttle = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA));
1261
+                                } else if (token === "queue" && tokens[0] === ":") {
1262
+                                    tokens.shift();
1263
+                                    triggerSpec.queue = consumeUntil(tokens, WHITESPACE_OR_COMMA);
1264
+                                } else if ((token === "root" || token === "threshold") && tokens[0] === ":") {
1265
+                                    tokens.shift();
1266
+                                    triggerSpec[token] = consumeUntil(tokens, WHITESPACE_OR_COMMA);
1267
+                                } else {
1268
+                                    triggerErrorEvent(elt, "htmx:syntax:error", {token:tokens.shift()});
1269
+                                }
1270
+                            }
1271
+                            triggerSpecs.push(triggerSpec);
1272
+                        }
1273
+                    }
1274
+                    if (tokens.length === initialLength) {
1275
+                        triggerErrorEvent(elt, "htmx:syntax:error", {token:tokens.shift()});
1276
+                    }
1277
+                    consumeUntil(tokens, NOT_WHITESPACE);
1278
+                } while (tokens[0] === "," && tokens.shift())
1279
+            }
1280
+
1281
+            if (triggerSpecs.length > 0) {
1282
+                return triggerSpecs;
1283
+            } else if (matches(elt, 'form')) {
1284
+                return [{trigger: 'submit'}];
1285
+            } else if (matches(elt, 'input[type="button"]')){
1286
+                return [{trigger: 'click'}];
1287
+            } else if (matches(elt, INPUT_SELECTOR)) {
1288
+                return [{trigger: 'change'}];
1289
+            } else {
1290
+                return [{trigger: 'click'}];
1291
+            }
1292
+        }
1293
+
1294
+        function cancelPolling(elt) {
1295
+            getInternalData(elt).cancelled = true;
1296
+        }
1297
+
1298
+        function processPolling(elt, handler, spec) {
1299
+            var nodeData = getInternalData(elt);
1300
+            nodeData.timeout = setTimeout(function () {
1301
+                if (bodyContains(elt) && nodeData.cancelled !== true) {
1302
+                    if (!maybeFilterEvent(spec, makeEvent('hx:poll:trigger', {triggerSpec:spec, target:elt}))) {
1303
+                        handler(elt);
1304
+                    }
1305
+                    processPolling(elt, handler, spec);
1306
+                }
1307
+            }, spec.pollInterval);
1308
+        }
1309
+
1310
+        function isLocalLink(elt) {
1311
+            return location.hostname === elt.hostname &&
1312
+                getRawAttribute(elt,'href') &&
1313
+                getRawAttribute(elt,'href').indexOf("#") !== 0;
1314
+        }
1315
+
1316
+        function boostElement(elt, nodeData, triggerSpecs) {
1317
+            if ((elt.tagName === "A" && isLocalLink(elt) && (elt.target === "" || elt.target === "_self")) || elt.tagName === "FORM") {
1318
+                nodeData.boosted = true;
1319
+                var verb, path;
1320
+                if (elt.tagName === "A") {
1321
+                    verb = "get";
1322
+                    path = elt.href; // DOM property gives the fully resolved href of a relative link
1323
+                } else {
1324
+                    var rawAttribute = getRawAttribute(elt, "method");
1325
+                    verb = rawAttribute ? rawAttribute.toLowerCase() : "get";
1326
+                    if (verb === "get") {
1327
+                    }
1328
+                    path = getRawAttribute(elt, 'action');
1329
+                }
1330
+                triggerSpecs.forEach(function(triggerSpec) {
1331
+                    addEventListener(elt, function(elt, evt) {
1332
+                        issueAjaxRequest(verb, path, elt, evt)
1333
+                    }, nodeData, triggerSpec, true);
1334
+                });
1335
+            }
1336
+        }
1337
+
1338
+        /**
1339
+         *
1340
+         * @param {Event} evt
1341
+         * @param {HTMLElement} elt
1342
+         * @returns
1343
+         */
1344
+        function shouldCancel(evt, elt) {
1345
+            if (evt.type === "submit" || evt.type === "click") {
1346
+                if (elt.tagName === "FORM") {
1347
+                    return true;
1348
+                }
1349
+                if (matches(elt, 'input[type="submit"], button') && closest(elt, 'form') !== null) {
1350
+                    return true;
1351
+                }
1352
+                if (elt.tagName === "A" && elt.href &&
1353
+                    (elt.getAttribute('href') === '#' || elt.getAttribute('href').indexOf("#") !== 0)) {
1354
+                    return true;
1355
+                }
1356
+            }
1357
+            return false;
1358
+        }
1359
+
1360
+        function ignoreBoostedAnchorCtrlClick(elt, evt) {
1361
+            return getInternalData(elt).boosted && elt.tagName === "A" && evt.type === "click" && (evt.ctrlKey || evt.metaKey);
1362
+        }
1363
+
1364
+        function maybeFilterEvent(triggerSpec, evt) {
1365
+            var eventFilter = triggerSpec.eventFilter;
1366
+            if(eventFilter){
1367
+                try {
1368
+                    return eventFilter(evt) !== true;
1369
+                } catch(e) {
1370
+                    triggerErrorEvent(getDocument().body, "htmx:eventFilter:error", {error: e, source:eventFilter.source});
1371
+                    return true;
1372
+                }
1373
+            }
1374
+            return false;
1375
+        }
1376
+
1377
+        function addEventListener(elt, handler, nodeData, triggerSpec, explicitCancel) {
1378
+            var elementData = getInternalData(elt);
1379
+            var eltsToListenOn;
1380
+            if (triggerSpec.from) {
1381
+                eltsToListenOn = querySelectorAllExt(elt, triggerSpec.from);
1382
+            } else {
1383
+                eltsToListenOn = [elt];
1384
+            }
1385
+            // store the initial value of the element so we can tell if it changes
1386
+            if (triggerSpec.changed) {
1387
+                elementData.lastValue = elt.value;
1388
+            }
1389
+            forEach(eltsToListenOn, function (eltToListenOn) {
1390
+                var eventListener = function (evt) {
1391
+                    if (!bodyContains(elt)) {
1392
+                        eltToListenOn.removeEventListener(triggerSpec.trigger, eventListener);
1393
+                        return;
1394
+                    }
1395
+                    if (ignoreBoostedAnchorCtrlClick(elt, evt)) {
1396
+                        return;
1397
+                    }
1398
+                    if (explicitCancel || shouldCancel(evt, elt)) {
1399
+                        evt.preventDefault();
1400
+                    }
1401
+                    if (maybeFilterEvent(triggerSpec, evt)) {
1402
+                        return;
1403
+                    }
1404
+                    var eventData = getInternalData(evt);
1405
+                    eventData.triggerSpec = triggerSpec;
1406
+                    if (eventData.handledFor == null) {
1407
+                        eventData.handledFor = [];
1408
+                    }
1409
+                    if (eventData.handledFor.indexOf(elt) < 0) {
1410
+                        eventData.handledFor.push(elt);
1411
+                        if (triggerSpec.consume) {
1412
+                            evt.stopPropagation();
1413
+                        }
1414
+                        if (triggerSpec.target && evt.target) {
1415
+                            if (!matches(evt.target, triggerSpec.target)) {
1416
+                                return;
1417
+                            }
1418
+                        }
1419
+                        if (triggerSpec.once) {
1420
+                            if (elementData.triggeredOnce) {
1421
+                                return;
1422
+                            } else {
1423
+                                elementData.triggeredOnce = true;
1424
+                            }
1425
+                        }
1426
+                        if (triggerSpec.changed) {
1427
+                            if (elementData.lastValue === elt.value) {
1428
+                                return;
1429
+                            } else {
1430
+                                elementData.lastValue = elt.value;
1431
+                            }
1432
+                        }
1433
+                        if (elementData.delayed) {
1434
+                            clearTimeout(elementData.delayed);
1435
+                        }
1436
+                        if (elementData.throttle) {
1437
+                            return;
1438
+                        }
1439
+
1440
+                        if (triggerSpec.throttle) {
1441
+                            if (!elementData.throttle) {
1442
+                                handler(elt, evt);
1443
+                                elementData.throttle = setTimeout(function () {
1444
+                                    elementData.throttle = null;
1445
+                                }, triggerSpec.throttle);
1446
+                            }
1447
+                        } else if (triggerSpec.delay) {
1448
+                            elementData.delayed = setTimeout(function() { handler(elt, evt) }, triggerSpec.delay);
1449
+                        } else {
1450
+                            triggerEvent(elt, 'htmx:trigger')
1451
+                            handler(elt, evt);
1452
+                        }
1453
+                    }
1454
+                };
1455
+                if (nodeData.listenerInfos == null) {
1456
+                    nodeData.listenerInfos = [];
1457
+                }
1458
+                nodeData.listenerInfos.push({
1459
+                    trigger: triggerSpec.trigger,
1460
+                    listener: eventListener,
1461
+                    on: eltToListenOn
1462
+                })
1463
+                eltToListenOn.addEventListener(triggerSpec.trigger, eventListener);
1464
+            });
1465
+        }
1466
+
1467
+        var windowIsScrolling = false // used by initScrollHandler
1468
+        var scrollHandler = null;
1469
+        function initScrollHandler() {
1470
+            if (!scrollHandler) {
1471
+                scrollHandler = function() {
1472
+                    windowIsScrolling = true
1473
+                };
1474
+                window.addEventListener("scroll", scrollHandler)
1475
+                setInterval(function() {
1476
+                    if (windowIsScrolling) {
1477
+                        windowIsScrolling = false;
1478
+                        forEach(getDocument().querySelectorAll("[hx-trigger='revealed'],[data-hx-trigger='revealed']"), function (elt) {
1479
+                            maybeReveal(elt);
1480
+                        })
1481
+                    }
1482
+                }, 200);
1483
+            }
1484
+        }
1485
+
1486
+        function maybeReveal(elt) {
1487
+            if (!hasAttribute(elt,'data-hx-revealed') && isScrolledIntoView(elt)) {
1488
+                elt.setAttribute('data-hx-revealed', 'true');
1489
+                var nodeData = getInternalData(elt);
1490
+                if (nodeData.initHash) {
1491
+                    triggerEvent(elt, 'revealed');
1492
+                } else {
1493
+                    // if the node isn't initialized, wait for it before triggering the request
1494
+                    elt.addEventListener("htmx:afterProcessNode", function(evt) { triggerEvent(elt, 'revealed') }, {once: true});
1495
+                }
1496
+            }
1497
+        }
1498
+
1499
+        //====================================================================
1500
+        // Web Sockets
1501
+        //====================================================================
1502
+
1503
+        function processWebSocketInfo(elt, nodeData, info) {
1504
+            var values = splitOnWhitespace(info);
1505
+            for (var i = 0; i < values.length; i++) {
1506
+                var value = values[i].split(/:(.+)/);
1507
+                if (value[0] === "connect") {
1508
+                    ensureWebSocket(elt, value[1], 0);
1509
+                }
1510
+                if (value[0] === "send") {
1511
+                    processWebSocketSend(elt);
1512
+                }
1513
+            }
1514
+        }
1515
+
1516
+        function ensureWebSocket(elt, wssSource, retryCount) {
1517
+            if (!bodyContains(elt)) {
1518
+                return;  // stop ensuring websocket connection when socket bearing element ceases to exist
1519
+            }
1520
+
1521
+            if (wssSource.indexOf("/") == 0) {  // complete absolute paths only
1522
+                var base_part = location.hostname + (location.port ? ':'+location.port: '');
1523
+                if (location.protocol == 'https:') {
1524
+                    wssSource = "wss://" + base_part + wssSource;
1525
+                } else if (location.protocol == 'http:') {
1526
+                    wssSource = "ws://" + base_part + wssSource;
1527
+                }
1528
+            }
1529
+            var socket = htmx.createWebSocket(wssSource);
1530
+            socket.onerror = function (e) {
1531
+                triggerErrorEvent(elt, "htmx:wsError", {error:e, socket:socket});
1532
+                maybeCloseWebSocketSource(elt);
1533
+            };
1534
+
1535
+            socket.onclose = function (e) {
1536
+                if ([1006, 1012, 1013].indexOf(e.code) >= 0) {  // Abnormal Closure/Service Restart/Try Again Later
1537
+                    var delay = getWebSocketReconnectDelay(retryCount);
1538
+                    setTimeout(function() {
1539
+                        ensureWebSocket(elt, wssSource, retryCount+1);  // creates a websocket with a new timeout
1540
+                    }, delay);
1541
+                }
1542
+            };
1543
+            socket.onopen = function (e) {
1544
+                retryCount = 0;
1545
+            }
1546
+
1547
+            getInternalData(elt).webSocket = socket;
1548
+            socket.addEventListener('message', function (event) {
1549
+                if (maybeCloseWebSocketSource(elt)) {
1550
+                    return;
1551
+                }
1552
+
1553
+                var response = event.data;
1554
+                withExtensions(elt, function(extension){
1555
+                    response = extension.transformResponse(response, null, elt);
1556
+                });
1557
+
1558
+                var settleInfo = makeSettleInfo(elt);
1559
+                var fragment = makeFragment(response);
1560
+                var children = toArray(fragment.children);
1561
+                for (var i = 0; i < children.length; i++) {
1562
+                    var child = children[i];
1563
+                    oobSwap(getAttributeValue(child, "hx-swap-oob") || "true", child, settleInfo);
1564
+                }
1565
+
1566
+                settleImmediately(settleInfo.tasks);
1567
+            });
1568
+        }
1569
+
1570
+        function maybeCloseWebSocketSource(elt) {
1571
+            if (!bodyContains(elt)) {
1572
+                getInternalData(elt).webSocket.close();
1573
+                return true;
1574
+            }
1575
+        }
1576
+
1577
+        function processWebSocketSend(elt) {
1578
+            var webSocketSourceElt = getClosestMatch(elt, function (parent) {
1579
+                return getInternalData(parent).webSocket != null;
1580
+            });
1581
+            if (webSocketSourceElt) {
1582
+                elt.addEventListener(getTriggerSpecs(elt)[0].trigger, function (evt) {
1583
+                    var webSocket = getInternalData(webSocketSourceElt).webSocket;
1584
+                    var headers = getHeaders(elt, webSocketSourceElt);
1585
+                    var results = getInputValues(elt, 'post');
1586
+                    var errors = results.errors;
1587
+                    var rawParameters = results.values;
1588
+                    var expressionVars = getExpressionVars(elt);
1589
+                    var allParameters = mergeObjects(rawParameters, expressionVars);
1590
+                    var filteredParameters = filterValues(allParameters, elt);
1591
+                    filteredParameters['HEADERS'] = headers;
1592
+                    if (errors && errors.length > 0) {
1593
+                        triggerEvent(elt, 'htmx:validation:halted', errors);
1594
+                        return;
1595
+                    }
1596
+                    webSocket.send(JSON.stringify(filteredParameters));
1597
+                    if(shouldCancel(evt, elt)){
1598
+                        evt.preventDefault();
1599
+                    }
1600
+                });
1601
+            } else {
1602
+                triggerErrorEvent(elt, "htmx:noWebSocketSourceError");
1603
+            }
1604
+        }
1605
+
1606
+        function getWebSocketReconnectDelay(retryCount) {
1607
+            var delay = htmx.config.wsReconnectDelay;
1608
+            if (typeof delay === 'function') {
1609
+                // @ts-ignore
1610
+                return delay(retryCount);
1611
+            }
1612
+            if (delay === 'full-jitter') {
1613
+                var exp = Math.min(retryCount, 6);
1614
+                var maxDelay = 1000 * Math.pow(2, exp);
1615
+                return maxDelay * Math.random();
1616
+            }
1617
+            logError('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"');
1618
+        }
1619
+
1620
+        //====================================================================
1621
+        // Server Sent Events
1622
+        //====================================================================
1623
+
1624
+        function processSSEInfo(elt, nodeData, info) {
1625
+            var values = splitOnWhitespace(info);
1626
+            for (var i = 0; i < values.length; i++) {
1627
+                var value = values[i].split(/:(.+)/);
1628
+                if (value[0] === "connect") {
1629
+                    processSSESource(elt, value[1]);
1630
+                }
1631
+
1632
+                if ((value[0] === "swap")) {
1633
+                    processSSESwap(elt, value[1])
1634
+                }
1635
+            }
1636
+        }
1637
+
1638
+        function processSSESource(elt, sseSrc) {
1639
+            var source = htmx.createEventSource(sseSrc);
1640
+            source.onerror = function (e) {
1641
+                triggerErrorEvent(elt, "htmx:sseError", {error:e, source:source});
1642
+                maybeCloseSSESource(elt);
1643
+            };
1644
+            getInternalData(elt).sseEventSource = source;
1645
+        }
1646
+
1647
+        function processSSESwap(elt, sseEventName) {
1648
+            var sseSourceElt = getClosestMatch(elt, hasEventSource);
1649
+            if (sseSourceElt) {
1650
+                var sseEventSource = getInternalData(sseSourceElt).sseEventSource;
1651
+                var sseListener = function (event) {
1652
+                    if (maybeCloseSSESource(sseSourceElt)) {
1653
+                        sseEventSource.removeEventListener(sseEventName, sseListener);
1654
+                        return;
1655
+                    }
1656
+
1657
+                    ///////////////////////////
1658
+                    // TODO: merge this code with AJAX and WebSockets code in the future.
1659
+
1660
+                    var response = event.data;
1661
+                    withExtensions(elt, function(extension){
1662
+                        response = extension.transformResponse(response, null, elt);
1663
+                    });
1664
+
1665
+                    var swapSpec = getSwapSpecification(elt)
1666
+                    var target = getTarget(elt)
1667
+                    var settleInfo = makeSettleInfo(elt);
1668
+
1669
+                    selectAndSwap(swapSpec.swapStyle, elt, target, response, settleInfo)
1670
+                    settleImmediately(settleInfo.tasks)
1671
+                    triggerEvent(elt, "htmx:sseMessage", event)
1672
+                };
1673
+
1674
+                getInternalData(elt).sseListener = sseListener;
1675
+                sseEventSource.addEventListener(sseEventName, sseListener);
1676
+            } else {
1677
+                triggerErrorEvent(elt, "htmx:noSSESourceError");
1678
+            }
1679
+        }
1680
+
1681
+        function processSSETrigger(elt, handler, sseEventName) {
1682
+            var sseSourceElt = getClosestMatch(elt, hasEventSource);
1683
+            if (sseSourceElt) {
1684
+                var sseEventSource = getInternalData(sseSourceElt).sseEventSource;
1685
+                var sseListener = function () {
1686
+                    if (!maybeCloseSSESource(sseSourceElt)) {
1687
+                        if (bodyContains(elt)) {
1688
+                            handler(elt);
1689
+                        } else {
1690
+                            sseEventSource.removeEventListener(sseEventName, sseListener);
1691
+                        }
1692
+                    }
1693
+                };
1694
+                getInternalData(elt).sseListener = sseListener;
1695
+                sseEventSource.addEventListener(sseEventName, sseListener);
1696
+            } else {
1697
+                triggerErrorEvent(elt, "htmx:noSSESourceError");
1698
+            }
1699
+        }
1700
+
1701
+        function maybeCloseSSESource(elt) {
1702
+            if (!bodyContains(elt)) {
1703
+                getInternalData(elt).sseEventSource.close();
1704
+                return true;
1705
+            }
1706
+        }
1707
+
1708
+        function hasEventSource(node) {
1709
+            return getInternalData(node).sseEventSource != null;
1710
+        }
1711
+
1712
+        //====================================================================
1713
+
1714
+        function loadImmediately(elt, handler, nodeData, delay) {
1715
+            var load = function(){
1716
+                if (!nodeData.loaded) {
1717
+                    nodeData.loaded = true;
1718
+                    handler(elt);
1719
+                }
1720
+            }
1721
+            if (delay) {
1722
+                setTimeout(load, delay);
1723
+            } else {
1724
+                load();
1725
+            }
1726
+        }
1727
+
1728
+        function processVerbs(elt, nodeData, triggerSpecs) {
1729
+            var explicitAction = false;
1730
+            forEach(VERBS, function (verb) {
1731
+                if (hasAttribute(elt,'hx-' + verb)) {
1732
+                    var path = getAttributeValue(elt, 'hx-' + verb);
1733
+                    explicitAction = true;
1734
+                    nodeData.path = path;
1735
+                    nodeData.verb = verb;
1736
+                    triggerSpecs.forEach(function(triggerSpec) {
1737
+                        addTriggerHandler(elt, triggerSpec, nodeData, function (elt, evt) {
1738
+                            issueAjaxRequest(verb, path, elt, evt)
1739
+                        })
1740
+                    });
1741
+                }
1742
+            });
1743
+            return explicitAction;
1744
+        }
1745
+
1746
+        function addTriggerHandler(elt, triggerSpec, nodeData, handler) {
1747
+            if (triggerSpec.sseEvent) {
1748
+                processSSETrigger(elt, handler, triggerSpec.sseEvent);
1749
+            } else if (triggerSpec.trigger === "revealed") {
1750
+                initScrollHandler();
1751
+                addEventListener(elt, handler, nodeData, triggerSpec);
1752
+                maybeReveal(elt);
1753
+            } else if (triggerSpec.trigger === "intersect") {
1754
+                var observerOptions = {};
1755
+                if (triggerSpec.root) {
1756
+                    observerOptions.root = querySelectorExt(elt, triggerSpec.root)
1757
+                }
1758
+                if (triggerSpec.threshold) {
1759
+                    observerOptions.threshold = parseFloat(triggerSpec.threshold);
1760
+                }
1761
+                var observer = new IntersectionObserver(function (entries) {
1762
+                    for (var i = 0; i < entries.length; i++) {
1763
+                        var entry = entries[i];
1764
+                        if (entry.isIntersecting) {
1765
+                            triggerEvent(elt, "intersect");
1766
+                            break;
1767
+                        }
1768
+                    }
1769
+                }, observerOptions);
1770
+                observer.observe(elt);
1771
+                addEventListener(elt, handler, nodeData, triggerSpec);
1772
+            } else if (triggerSpec.trigger === "load") {
1773
+                if (!maybeFilterEvent(triggerSpec, makeEvent("load", {elt:elt}))) {
1774
+                                loadImmediately(elt, handler, nodeData, triggerSpec.delay);
1775
+                            }
1776
+            } else if (triggerSpec.pollInterval) {
1777
+                nodeData.polling = true;
1778
+                processPolling(elt, handler, triggerSpec);
1779
+            } else {
1780
+                addEventListener(elt, handler, nodeData, triggerSpec);
1781
+            }
1782
+        }
1783
+
1784
+        function evalScript(script) {
1785
+            if (script.type === "text/javascript" || script.type === "module" || script.type === "") {
1786
+                var newScript = getDocument().createElement("script");
1787
+                forEach(script.attributes, function (attr) {
1788
+                    newScript.setAttribute(attr.name, attr.value);
1789
+                });
1790
+                newScript.textContent = script.textContent;
1791
+                newScript.async = false;
1792
+                if (htmx.config.inlineScriptNonce) {
1793
+                    newScript.nonce = htmx.config.inlineScriptNonce;
1794
+                }
1795
+                var parent = script.parentElement;
1796
+
1797
+                try {
1798
+                    parent.insertBefore(newScript, script);
1799
+                } catch (e) {
1800
+                    logError(e);
1801
+                } finally {
1802
+                    // remove old script element, but only if it is still in DOM
1803
+                    if (script.parentElement) {
1804
+                        script.parentElement.removeChild(script);
1805
+                    }
1806
+                }
1807
+            }
1808
+        }
1809
+
1810
+        function processScripts(elt) {
1811
+            if (matches(elt, "script")) {
1812
+                evalScript(elt);
1813
+            }
1814
+            forEach(findAll(elt, "script"), function (script) {
1815
+                evalScript(script);
1816
+            });
1817
+        }
1818
+
1819
+        function hasChanceOfBeingBoosted() {
1820
+            return document.querySelector("[hx-boost], [data-hx-boost]");
1821
+        }
1822
+
1823
+        function findElementsToProcess(elt) {
1824
+            if (elt.querySelectorAll) {
1825
+                var boostedElts = hasChanceOfBeingBoosted() ? ", a, form" : "";
1826
+                var results = elt.querySelectorAll(VERB_SELECTOR + boostedElts + ", [hx-sse], [data-hx-sse], [hx-ws]," +
1827
+                    " [data-hx-ws], [hx-ext], [data-hx-ext], [hx-trigger], [data-hx-trigger], [hx-on], [data-hx-on]");
1828
+                return results;
1829
+            } else {
1830
+                return [];
1831
+            }
1832
+        }
1833
+
1834
+        function initButtonTracking(form){
1835
+            var maybeSetLastButtonClicked = function(evt){
1836
+                var elt = closest(evt.target, "button, input[type='submit']");
1837
+                if (elt !== null) {
1838
+                    var internalData = getInternalData(form);
1839
+                    internalData.lastButtonClicked = elt;
1840
+                }
1841
+            };
1842
+
1843
+            // need to handle both click and focus in:
1844
+            //   focusin - in case someone tabs in to a button and hits the space bar
1845
+            //   click - on OSX buttons do not focus on click see https://bugs.webkit.org/show_bug.cgi?id=13724
1846
+
1847
+            form.addEventListener('click', maybeSetLastButtonClicked)
1848
+            form.addEventListener('focusin', maybeSetLastButtonClicked)
1849
+            form.addEventListener('focusout', function(evt){
1850
+                var internalData = getInternalData(form);
1851
+                internalData.lastButtonClicked = null;
1852
+            })
1853
+        }
1854
+
1855
+        function countCurlies(line) {
1856
+            var tokens = tokenizeString(line);
1857
+            var netCurlies = 0;
1858
+            for (let i = 0; i < tokens.length; i++) {
1859
+                const token = tokens[i];
1860
+                if (token === "{") {
1861
+                    netCurlies++;
1862
+                } else if (token === "}") {
1863
+                    netCurlies--;
1864
+                }
1865
+            }
1866
+            return netCurlies;
1867
+        }
1868
+
1869
+        function addHxOnEventHandler(elt, eventName, code) {
1870
+            var nodeData = getInternalData(elt);
1871
+            nodeData.onHandlers = [];
1872
+            var func = new Function("event", code + "; return;");
1873
+            var listener = elt.addEventListener(eventName, function (e) {
1874
+                return func.call(elt, e);
1875
+            });
1876
+            nodeData.onHandlers.push({event:eventName, listener:listener});
1877
+            return {nodeData, code, func, listener};
1878
+        }
1879
+
1880
+        function processHxOn(elt) {
1881
+            var hxOnValue = getAttributeValue(elt, 'hx-on');
1882
+            if (hxOnValue) {
1883
+                var handlers = {}
1884
+                var lines = hxOnValue.split("\n");
1885
+                var currentEvent = null;
1886
+                var curlyCount = 0;
1887
+                while (lines.length > 0) {
1888
+                    var line = lines.shift();
1889
+                    var match = line.match(/^\s*([a-zA-Z:\-]+:)(.*)/);
1890
+                    if (curlyCount === 0 && match) {
1891
+                        line.split(":")
1892
+                        currentEvent = match[1].slice(0, -1); // strip last colon
1893
+                        handlers[currentEvent] = match[2];
1894
+                    } else {
1895
+                        handlers[currentEvent] += line;
1896
+                    }
1897
+                    curlyCount += countCurlies(line);
1898
+                }
1899
+
1900
+                for (var eventName in handlers) {
1901
+                    addHxOnEventHandler(elt, eventName, handlers[eventName]);
1902
+                }
1903
+            }
1904
+        }
1905
+
1906
+        function initNode(elt) {
1907
+            if (elt.closest && elt.closest(htmx.config.disableSelector)) {
1908
+                return;
1909
+            }
1910
+            var nodeData = getInternalData(elt);
1911
+            if (nodeData.initHash !== attributeHash(elt)) {
1912
+
1913
+                nodeData.initHash = attributeHash(elt);
1914
+
1915
+                // clean up any previously processed info
1916
+                deInitNode(elt);
1917
+
1918
+                processHxOn(elt);
1919
+
1920
+                triggerEvent(elt, "htmx:beforeProcessNode")
1921
+
1922
+                if (elt.value) {
1923
+                    nodeData.lastValue = elt.value;
1924
+                }
1925
+
1926
+                var triggerSpecs = getTriggerSpecs(elt);
1927
+                var hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs);
1928
+
1929
+                if (!hasExplicitHttpAction) {
1930
+                    if (getClosestAttributeValue(elt, "hx-boost") === "true") {
1931
+                        boostElement(elt, nodeData, triggerSpecs);
1932
+                    } else if (hasAttribute(elt, 'hx-trigger')) {
1933
+                        triggerSpecs.forEach(function (triggerSpec) {
1934
+                            // For "naked" triggers, don't do anything at all
1935
+                            addTriggerHandler(elt, triggerSpec, nodeData, function () {
1936
+                            })
1937
+                        })
1938
+                    }
1939
+                }
1940
+
1941
+                if (elt.tagName === "FORM") {
1942
+                    initButtonTracking(elt);
1943
+                }
1944
+
1945
+                var sseInfo = getAttributeValue(elt, 'hx-sse');
1946
+                if (sseInfo) {
1947
+                    processSSEInfo(elt, nodeData, sseInfo);
1948
+                }
1949
+
1950
+                var wsInfo = getAttributeValue(elt, 'hx-ws');
1951
+                if (wsInfo) {
1952
+                    processWebSocketInfo(elt, nodeData, wsInfo);
1953
+                }
1954
+                triggerEvent(elt, "htmx:afterProcessNode");
1955
+            }
1956
+        }
1957
+
1958
+        function processNode(elt) {
1959
+            elt = resolveTarget(elt);
1960
+            initNode(elt);
1961
+            forEach(findElementsToProcess(elt), function(child) { initNode(child) });
1962
+        }
1963
+
1964
+        //====================================================================
1965
+        // Event/Log Support
1966
+        //====================================================================
1967
+
1968
+        function kebabEventName(str) {
1969
+            return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
1970
+        }
1971
+
1972
+        function makeEvent(eventName, detail) {
1973
+            var evt;
1974
+            if (window.CustomEvent && typeof window.CustomEvent === 'function') {
1975
+                evt = new CustomEvent(eventName, {bubbles: true, cancelable: true, detail: detail});
1976
+            } else {
1977
+                evt = getDocument().createEvent('CustomEvent');
1978
+                evt.initCustomEvent(eventName, true, true, detail);
1979
+            }
1980
+            return evt;
1981
+        }
1982
+
1983
+        function triggerErrorEvent(elt, eventName, detail) {
1984
+            triggerEvent(elt, eventName, mergeObjects({error:eventName}, detail));
1985
+        }
1986
+
1987
+        function ignoreEventForLogging(eventName) {
1988
+            return eventName === "htmx:afterProcessNode"
1989
+        }
1990
+
1991
+        /**
1992
+         * `withExtensions` locates all active extensions for a provided element, then
1993
+         * executes the provided function using each of the active extensions.  It should
1994
+         * be called internally at every extendable execution point in htmx.
1995
+         *
1996
+         * @param {HTMLElement} elt
1997
+         * @param {(extension:import("./htmx").HtmxExtension) => void} toDo
1998
+         * @returns void
1999
+         */
2000
+        function withExtensions(elt, toDo) {
2001
+            forEach(getExtensions(elt), function(extension){
2002
+                try {
2003
+                    toDo(extension);
2004
+                } catch (e) {
2005
+                    logError(e);
2006
+                }
2007
+            });
2008
+        }
2009
+
2010
+        function logError(msg) {
2011
+            if(console.error) {
2012
+                console.error(msg);
2013
+            } else if (console.log) {
2014
+                console.log("ERROR: ", msg);
2015
+            }
2016
+        }
2017
+
2018
+        function triggerEvent(elt, eventName, detail) {
2019
+            elt = resolveTarget(elt);
2020
+            if (detail == null) {
2021
+                detail = {};
2022
+            }
2023
+            detail["elt"] = elt;
2024
+            var event = makeEvent(eventName, detail);
2025
+            if (htmx.logger && !ignoreEventForLogging(eventName)) {
2026
+                htmx.logger(elt, eventName, detail);
2027
+            }
2028
+            if (detail.error) {
2029
+                logError(detail.error);
2030
+                triggerEvent(elt, "htmx:error", {errorInfo:detail})
2031
+            }
2032
+            var eventResult = elt.dispatchEvent(event);
2033
+            var kebabName = kebabEventName(eventName);
2034
+            if (eventResult && kebabName !== eventName) {
2035
+                var kebabedEvent = makeEvent(kebabName, event.detail);
2036
+                eventResult = eventResult && elt.dispatchEvent(kebabedEvent)
2037
+            }
2038
+            withExtensions(elt, function (extension) {
2039
+                eventResult = eventResult && (extension.onEvent(eventName, event) !== false)
2040
+            });
2041
+            return eventResult;
2042
+        }
2043
+
2044
+        //====================================================================
2045
+        // History Support
2046
+        //====================================================================
2047
+        var currentPathForHistory = location.pathname+location.search;
2048
+
2049
+        function getHistoryElement() {
2050
+            var historyElt = getDocument().querySelector('[hx-history-elt],[data-hx-history-elt]');
2051
+            return historyElt || getDocument().body;
2052
+        }
2053
+
2054
+        function saveToHistoryCache(url, content, title, scroll) {
2055
+            if (!canAccessLocalStorage()) {
2056
+                return;
2057
+            }
2058
+
2059
+            url = normalizePath(url);
2060
+
2061
+            var historyCache = parseJSON(localStorage.getItem("htmx-history-cache")) || [];
2062
+            for (var i = 0; i < historyCache.length; i++) {
2063
+                if (historyCache[i].url === url) {
2064
+                    historyCache.splice(i, 1);
2065
+                    break;
2066
+                }
2067
+            }
2068
+            var newHistoryItem = {url:url, content: content, title:title, scroll:scroll};
2069
+            triggerEvent(getDocument().body, "htmx:historyItemCreated", {item:newHistoryItem, cache: historyCache})
2070
+            historyCache.push(newHistoryItem)
2071
+            while (historyCache.length > htmx.config.historyCacheSize) {
2072
+                historyCache.shift();
2073
+            }
2074
+            while(historyCache.length > 0){
2075
+                try {
2076
+                    localStorage.setItem("htmx-history-cache", JSON.stringify(historyCache));
2077
+                    break;
2078
+                } catch (e) {
2079
+                    triggerErrorEvent(getDocument().body, "htmx:historyCacheError", {cause:e, cache: historyCache})
2080
+                    historyCache.shift(); // shrink the cache and retry
2081
+                }
2082
+            }
2083
+        }
2084
+
2085
+        function getCachedHistory(url) {
2086
+            if (!canAccessLocalStorage()) {
2087
+                return null;
2088
+            }
2089
+
2090
+            url = normalizePath(url);
2091
+
2092
+            var historyCache = parseJSON(localStorage.getItem("htmx-history-cache")) || [];
2093
+            for (var i = 0; i < historyCache.length; i++) {
2094
+                if (historyCache[i].url === url) {
2095
+                    return historyCache[i];
2096
+                }
2097
+            }
2098
+            return null;
2099
+        }
2100
+
2101
+        function cleanInnerHtmlForHistory(elt) {
2102
+            var className = htmx.config.requestClass;
2103
+            var clone = elt.cloneNode(true);
2104
+            forEach(findAll(clone, "." + className), function(child){
2105
+                removeClassFromElement(child, className);
2106
+            });
2107
+            return clone.innerHTML;
2108
+        }
2109
+
2110
+        function saveCurrentPageToHistory() {
2111
+            var elt = getHistoryElement();
2112
+            var path = currentPathForHistory || location.pathname+location.search;
2113
+
2114
+            // Allow history snapshot feature to be disabled where hx-history="false"
2115
+            // is present *anywhere* in the current document we're about to save,
2116
+            // so we can prevent privileged data entering the cache.
2117
+            // The page will still be reachable as a history entry, but htmx will fetch it
2118
+            // live from the server onpopstate rather than look in the localStorage cache
2119
+            var disableHistoryCache = getDocument().querySelector('[hx-history="false" i],[data-hx-history="false" i]');
2120
+            if (!disableHistoryCache) {
2121
+                triggerEvent(getDocument().body, "htmx:beforeHistorySave", {path: path, historyElt: elt});
2122
+                saveToHistoryCache(path, cleanInnerHtmlForHistory(elt), getDocument().title, window.scrollY);
2123
+            }
2124
+
2125
+            if (htmx.config.historyEnabled) history.replaceState({htmx: true}, getDocument().title, window.location.href);
2126
+        }
2127
+
2128
+        function pushUrlIntoHistory(path) {
2129
+            // remove the cache buster parameter, if any
2130
+            if (htmx.config.getCacheBusterParam) {
2131
+                path = path.replace(/org\.htmx\.cache-buster=[^&]*&?/, '')
2132
+                if (path.endsWith('&') || path.endsWith("?")) {
2133
+                    path = path.slice(0, -1);
2134
+                }
2135
+            }
2136
+            if(htmx.config.historyEnabled) {
2137
+                history.pushState({htmx:true}, "", path);
2138
+            }
2139
+            currentPathForHistory = path;
2140
+        }
2141
+
2142
+        function replaceUrlInHistory(path) {
2143
+            if(htmx.config.historyEnabled)  history.replaceState({htmx:true}, "", path);
2144
+            currentPathForHistory = path;
2145
+        }
2146
+
2147
+        function settleImmediately(tasks) {
2148
+            forEach(tasks, function (task) {
2149
+                task.call();
2150
+            });
2151
+        }
2152
+
2153
+        function loadHistoryFromServer(path) {
2154
+            var request = new XMLHttpRequest();
2155
+            var details = {path: path, xhr:request};
2156
+            triggerEvent(getDocument().body, "htmx:historyCacheMiss", details);
2157
+            request.open('GET', path, true);
2158
+            request.setRequestHeader("HX-History-Restore-Request", "true");
2159
+            request.onload = function () {
2160
+                if (this.status >= 200 && this.status < 400) {
2161
+                    triggerEvent(getDocument().body, "htmx:historyCacheMissLoad", details);
2162
+                    var fragment = makeFragment(this.response);
2163
+                    // @ts-ignore
2164
+                    fragment = fragment.querySelector('[hx-history-elt],[data-hx-history-elt]') || fragment;
2165
+                    var historyElement = getHistoryElement();
2166
+                    var settleInfo = makeSettleInfo(historyElement);
2167
+                    var title = findTitle(this.response);
2168
+                    if (title) {
2169
+                        var titleElt = find("title");
2170
+                        if (titleElt) {
2171
+                            titleElt.innerHTML = title;
2172
+                        } else {
2173
+                            window.document.title = title;
2174
+                        }
2175
+                    }
2176
+                    // @ts-ignore
2177
+                    swapInnerHTML(historyElement, fragment, settleInfo)
2178
+                    settleImmediately(settleInfo.tasks);
2179
+                    currentPathForHistory = path;
2180
+                    triggerEvent(getDocument().body, "htmx:historyRestore", {path: path, cacheMiss:true, serverResponse:this.response});
2181
+                } else {
2182
+                    triggerErrorEvent(getDocument().body, "htmx:historyCacheMissLoadError", details);
2183
+                }
2184
+            };
2185
+            request.send();
2186
+        }
2187
+
2188
+        function restoreHistory(path) {
2189
+            saveCurrentPageToHistory();
2190
+            path = path || location.pathname+location.search;
2191
+            var cached = getCachedHistory(path);
2192
+            if (cached) {
2193
+                var fragment = makeFragment(cached.content);
2194
+                var historyElement = getHistoryElement();
2195
+                var settleInfo = makeSettleInfo(historyElement);
2196
+                swapInnerHTML(historyElement, fragment, settleInfo)
2197
+                settleImmediately(settleInfo.tasks);
2198
+                document.title = cached.title;
2199
+                window.scrollTo(0, cached.scroll);
2200
+                currentPathForHistory = path;
2201
+                triggerEvent(getDocument().body, "htmx:historyRestore", {path:path, item:cached});
2202
+            } else {
2203
+                if (htmx.config.refreshOnHistoryMiss) {
2204
+
2205
+                    // @ts-ignore: optional parameter in reload() function throws error
2206
+                    window.location.reload(true);
2207
+                } else {
2208
+                    loadHistoryFromServer(path);
2209
+                }
2210
+            }
2211
+        }
2212
+
2213
+        function addRequestIndicatorClasses(elt) {
2214
+            var indicators = findAttributeTargets(elt, 'hx-indicator');
2215
+            if (indicators == null) {
2216
+                indicators = [elt];
2217
+            }
2218
+            forEach(indicators, function (ic) {
2219
+                var internalData = getInternalData(ic);
2220
+                internalData.requestCount = (internalData.requestCount || 0) + 1;
2221
+                ic.classList["add"].call(ic.classList, htmx.config.requestClass);
2222
+            });
2223
+            return indicators;
2224
+        }
2225
+
2226
+        function removeRequestIndicatorClasses(indicators) {
2227
+            forEach(indicators, function (ic) {
2228
+                var internalData = getInternalData(ic);
2229
+                internalData.requestCount = (internalData.requestCount || 0) - 1;
2230
+                if (internalData.requestCount === 0) {
2231
+                    ic.classList["remove"].call(ic.classList, htmx.config.requestClass);
2232
+                }
2233
+            });
2234
+        }
2235
+
2236
+        //====================================================================
2237
+        // Input Value Processing
2238
+        //====================================================================
2239
+
2240
+        function haveSeenNode(processed, elt) {
2241
+            for (var i = 0; i < processed.length; i++) {
2242
+                var node = processed[i];
2243
+                if (node.isSameNode(elt)) {
2244
+                    return true;
2245
+                }
2246
+            }
2247
+            return false;
2248
+        }
2249
+
2250
+        function shouldInclude(elt) {
2251
+            if(elt.name === "" || elt.name == null || elt.disabled) {
2252
+                return false;
2253
+            }
2254
+            // ignore "submitter" types (see jQuery src/serialize.js)
2255
+            if (elt.type === "button" || elt.type === "submit" || elt.tagName === "image" || elt.tagName === "reset" || elt.tagName === "file" ) {
2256
+                return false;
2257
+            }
2258
+            if (elt.type === "checkbox" || elt.type === "radio" ) {
2259
+                return elt.checked;
2260
+            }
2261
+            return true;
2262
+        }
2263
+
2264
+        function processInputValue(processed, values, errors, elt, validate) {
2265
+            if (elt == null || haveSeenNode(processed, elt)) {
2266
+                return;
2267
+            } else {
2268
+                processed.push(elt);
2269
+            }
2270
+            if (shouldInclude(elt)) {
2271
+                var name = getRawAttribute(elt,"name");
2272
+                var value = elt.value;
2273
+                if (elt.multiple) {
2274
+                    value = toArray(elt.querySelectorAll("option:checked")).map(function (e) { return e.value });
2275
+                }
2276
+                // include file inputs
2277
+                if (elt.files) {
2278
+                    value = toArray(elt.files);
2279
+                }
2280
+                // This is a little ugly because both the current value of the named value in the form
2281
+                // and the new value could be arrays, so we have to handle all four cases :/
2282
+                if (name != null && value != null) {
2283
+                    var current = values[name];
2284
+                    if (current !== undefined) {
2285
+                        if (Array.isArray(current)) {
2286
+                            if (Array.isArray(value)) {
2287
+                                values[name] = current.concat(value);
2288
+                            } else {
2289
+                                current.push(value);
2290
+                            }
2291
+                        } else {
2292
+                            if (Array.isArray(value)) {
2293
+                                values[name] = [current].concat(value);
2294
+                            } else {
2295
+                                values[name] = [current, value];
2296
+                            }
2297
+                        }
2298
+                    } else {
2299
+                        values[name] = value;
2300
+                    }
2301
+                }
2302
+                if (validate) {
2303
+                    validateElement(elt, errors);
2304
+                }
2305
+            }
2306
+            if (matches(elt, 'form')) {
2307
+                var inputs = elt.elements;
2308
+                forEach(inputs, function(input) {
2309
+                    processInputValue(processed, values, errors, input, validate);
2310
+                });
2311
+            }
2312
+        }
2313
+
2314
+        function validateElement(element, errors) {
2315
+            if (element.willValidate) {
2316
+                triggerEvent(element, "htmx:validation:validate")
2317
+                if (!element.checkValidity()) {
2318
+                    errors.push({elt: element, message:element.validationMessage, validity:element.validity});
2319
+                    triggerEvent(element, "htmx:validation:failed", {message:element.validationMessage, validity:element.validity})
2320
+                }
2321
+            }
2322
+        }
2323
+
2324
+        /**
2325
+         * @param {HTMLElement} elt
2326
+         * @param {string} verb
2327
+         */
2328
+        function getInputValues(elt, verb) {
2329
+            var processed = [];
2330
+            var values = {};
2331
+            var formValues = {};
2332
+            var errors = [];
2333
+            var internalData = getInternalData(elt);
2334
+
2335
+            // only validate when form is directly submitted and novalidate or formnovalidate are not set
2336
+            // or if the element has an explicit hx-validate="true" on it
2337
+            var validate = (matches(elt, 'form') && elt.noValidate !== true) || getAttributeValue(elt, "hx-validate") === "true";
2338
+            if (internalData.lastButtonClicked) {
2339
+                validate = validate && internalData.lastButtonClicked.formNoValidate !== true;
2340
+            }
2341
+
2342
+            // for a non-GET include the closest form
2343
+            if (verb !== 'get') {
2344
+                processInputValue(processed, formValues, errors, closest(elt, 'form'), validate);
2345
+            }
2346
+
2347
+            // include the element itself
2348
+            processInputValue(processed, values, errors, elt, validate);
2349
+
2350
+            // if a button or submit was clicked last, include its value
2351
+            if (internalData.lastButtonClicked) {
2352
+                var name = getRawAttribute(internalData.lastButtonClicked,"name");
2353
+                if (name) {
2354
+                    values[name] = internalData.lastButtonClicked.value;
2355
+                }
2356
+            }
2357
+
2358
+            // include any explicit includes
2359
+            var includes = findAttributeTargets(elt, "hx-include");
2360
+            forEach(includes, function(node) {
2361
+                processInputValue(processed, values, errors, node, validate);
2362
+                // if a non-form is included, include any input values within it
2363
+                if (!matches(node, 'form')) {
2364
+                    forEach(node.querySelectorAll(INPUT_SELECTOR), function (descendant) {
2365
+                        processInputValue(processed, values, errors, descendant, validate);
2366
+                    })
2367
+                }
2368
+            });
2369
+
2370
+            // form values take precedence, overriding the regular values
2371
+            values = mergeObjects(values, formValues);
2372
+
2373
+            return {errors:errors, values:values};
2374
+        }
2375
+
2376
+        function appendParam(returnStr, name, realValue) {
2377
+            if (returnStr !== "") {
2378
+                returnStr += "&";
2379
+            }
2380
+            if (String(realValue) === "[object Object]") {
2381
+                realValue = JSON.stringify(realValue);
2382
+            }
2383
+            var s = encodeURIComponent(realValue);
2384
+            returnStr += encodeURIComponent(name) + "=" + s;
2385
+            return returnStr;
2386
+        }
2387
+
2388
+        function urlEncode(values) {
2389
+            var returnStr = "";
2390
+            for (var name in values) {
2391
+                if (values.hasOwnProperty(name)) {
2392
+                    var value = values[name];
2393
+                    if (Array.isArray(value)) {
2394
+                        forEach(value, function(v) {
2395
+                            returnStr = appendParam(returnStr, name, v);
2396
+                        });
2397
+                    } else {
2398
+                        returnStr = appendParam(returnStr, name, value);
2399
+                    }
2400
+                }
2401
+            }
2402
+            return returnStr;
2403
+        }
2404
+
2405
+        function makeFormData(values) {
2406
+            var formData = new FormData();
2407
+            for (var name in values) {
2408
+                if (values.hasOwnProperty(name)) {
2409
+                    var value = values[name];
2410
+                    if (Array.isArray(value)) {
2411
+                        forEach(value, function(v) {
2412
+                            formData.append(name, v);
2413
+                        });
2414
+                    } else {
2415
+                        formData.append(name, value);
2416
+                    }
2417
+                }
2418
+            }
2419
+            return formData;
2420
+        }
2421
+
2422
+        //====================================================================
2423
+        // Ajax
2424
+        //====================================================================
2425
+
2426
+        /**
2427
+         * @param {HTMLElement} elt
2428
+         * @param {HTMLElement} target
2429
+         * @param {string} prompt
2430
+         * @returns {Object} // TODO: Define/Improve HtmxHeaderSpecification
2431
+         */
2432
+        function getHeaders(elt, target, prompt) {
2433
+            var headers = {
2434
+                "HX-Request" : "true",
2435
+                "HX-Trigger" : getRawAttribute(elt, "id"),
2436
+                "HX-Trigger-Name" : getRawAttribute(elt, "name"),
2437
+                "HX-Target" : getAttributeValue(target, "id"),
2438
+                "HX-Current-URL" : getDocument().location.href,
2439
+            }
2440
+            getValuesForElement(elt, "hx-headers", false, headers)
2441
+            if (prompt !== undefined) {
2442
+                headers["HX-Prompt"] = prompt;
2443
+            }
2444
+            if (getInternalData(elt).boosted) {
2445
+                headers["HX-Boosted"] = "true";
2446
+            }
2447
+            return headers;
2448
+        }
2449
+
2450
+        /**
2451
+         * filterValues takes an object containing form input values
2452
+         * and returns a new object that only contains keys that are
2453
+         * specified by the closest "hx-params" attribute
2454
+         * @param {Object} inputValues
2455
+         * @param {HTMLElement} elt
2456
+         * @returns {Object}
2457
+         */
2458
+        function filterValues(inputValues, elt) {
2459
+            var paramsValue = getClosestAttributeValue(elt, "hx-params");
2460
+            if (paramsValue) {
2461
+                if (paramsValue === "none") {
2462
+                    return {};
2463
+                } else if (paramsValue === "*") {
2464
+                    return inputValues;
2465
+                } else if(paramsValue.indexOf("not ") === 0) {
2466
+                    forEach(paramsValue.substr(4).split(","), function (name) {
2467
+                        name = name.trim();
2468
+                        delete inputValues[name];
2469
+                    });
2470
+                    return inputValues;
2471
+                } else {
2472
+                    var newValues = {}
2473
+                    forEach(paramsValue.split(","), function (name) {
2474
+                        name = name.trim();
2475
+                        newValues[name] = inputValues[name];
2476
+                    });
2477
+                    return newValues;
2478
+                }
2479
+            } else {
2480
+                return inputValues;
2481
+            }
2482
+        }
2483
+
2484
+        function isAnchorLink(elt) {
2485
+          return getRawAttribute(elt, 'href') && getRawAttribute(elt, 'href').indexOf("#") >=0
2486
+        }
2487
+
2488
+        /**
2489
+         *
2490
+         * @param {HTMLElement} elt
2491
+         * @param {string} swapInfoOverride
2492
+         * @returns {import("./htmx").HtmxSwapSpecification}
2493
+         */
2494
+        function getSwapSpecification(elt, swapInfoOverride) {
2495
+            var swapInfo = swapInfoOverride ? swapInfoOverride : getClosestAttributeValue(elt, "hx-swap");
2496
+            var swapSpec = {
2497
+                "swapStyle" : getInternalData(elt).boosted ? 'innerHTML' : htmx.config.defaultSwapStyle,
2498
+                "swapDelay" : htmx.config.defaultSwapDelay,
2499
+                "settleDelay" : htmx.config.defaultSettleDelay
2500
+            }
2501
+            if (getInternalData(elt).boosted && !isAnchorLink(elt)) {
2502
+              swapSpec["show"] = "top"
2503
+            }
2504
+            if (swapInfo) {
2505
+                var split = splitOnWhitespace(swapInfo);
2506
+                if (split.length > 0) {
2507
+                    swapSpec["swapStyle"] = split[0];
2508
+                    for (var i = 1; i < split.length; i++) {
2509
+                        var modifier = split[i];
2510
+                        if (modifier.indexOf("swap:") === 0) {
2511
+                            swapSpec["swapDelay"] = parseInterval(modifier.substr(5));
2512
+                        }
2513
+                        if (modifier.indexOf("settle:") === 0) {
2514
+                            swapSpec["settleDelay"] = parseInterval(modifier.substr(7));
2515
+                        }
2516
+                        if (modifier.indexOf("transition:") === 0) {
2517
+                            swapSpec["transition"] = modifier.substr(11) === "true";
2518
+                        }
2519
+                        if (modifier.indexOf("scroll:") === 0) {
2520
+                            var scrollSpec = modifier.substr(7);
2521
+                            var splitSpec = scrollSpec.split(":");
2522
+                            var scrollVal = splitSpec.pop();
2523
+                            var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null;
2524
+                            swapSpec["scroll"] = scrollVal;
2525
+                            swapSpec["scrollTarget"] = selectorVal;
2526
+                        }
2527
+                        if (modifier.indexOf("show:") === 0) {
2528
+                            var showSpec = modifier.substr(5);
2529
+                            var splitSpec = showSpec.split(":");
2530
+                            var showVal = splitSpec.pop();
2531
+                            var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null;
2532
+                            swapSpec["show"] = showVal;
2533
+                            swapSpec["showTarget"] = selectorVal;
2534
+                        }
2535
+                        if (modifier.indexOf("focus-scroll:") === 0) {
2536
+                            var focusScrollVal = modifier.substr("focus-scroll:".length);
2537
+                            swapSpec["focusScroll"] = focusScrollVal == "true";
2538
+                        }
2539
+                    }
2540
+                }
2541
+            }
2542
+            return swapSpec;
2543
+        }
2544
+
2545
+        function usesFormData(elt) {
2546
+            return getClosestAttributeValue(elt, "hx-encoding") === "multipart/form-data" ||
2547
+                (matches(elt, "form") && getRawAttribute(elt, 'enctype') === "multipart/form-data");
2548
+        }
2549
+
2550
+        function encodeParamsForBody(xhr, elt, filteredParameters) {
2551
+            var encodedParameters = null;
2552
+            withExtensions(elt, function (extension) {
2553
+                if (encodedParameters == null) {
2554
+                    encodedParameters = extension.encodeParameters(xhr, filteredParameters, elt);
2555
+                }
2556
+            });
2557
+            if (encodedParameters != null) {
2558
+                return encodedParameters;
2559
+            } else {
2560
+                if (usesFormData(elt)) {
2561
+                    return makeFormData(filteredParameters);
2562
+                } else {
2563
+                    return urlEncode(filteredParameters);
2564
+                }
2565
+            }
2566
+        }
2567
+
2568
+        /**
2569
+         *
2570
+         * @param {Element} target
2571
+         * @returns {import("./htmx").HtmxSettleInfo}
2572
+         */
2573
+        function makeSettleInfo(target) {
2574
+            return {tasks: [], elts: [target]};
2575
+        }
2576
+
2577
+        function updateScrollState(content, swapSpec) {
2578
+            var first = content[0];
2579
+            var last = content[content.length - 1];
2580
+            if (swapSpec.scroll) {
2581
+                var target = null;
2582
+                if (swapSpec.scrollTarget) {
2583
+                    target = querySelectorExt(first, swapSpec.scrollTarget);
2584
+                }
2585
+                if (swapSpec.scroll === "top" && (first || target)) {
2586
+                    target = target || first;
2587
+                    target.scrollTop = 0;
2588
+                }
2589
+                if (swapSpec.scroll === "bottom" && (last || target)) {
2590
+                    target = target || last;
2591
+                    target.scrollTop = target.scrollHeight;
2592
+                }
2593
+            }
2594
+            if (swapSpec.show) {
2595
+                var target = null;
2596
+                if (swapSpec.showTarget) {
2597
+                    var targetStr = swapSpec.showTarget;
2598
+                    if (swapSpec.showTarget === "window") {
2599
+                        targetStr = "body";
2600
+                    }
2601
+                    target = querySelectorExt(first, targetStr);
2602
+                }
2603
+                if (swapSpec.show === "top" && (first || target)) {
2604
+                    target = target || first;
2605
+                    target.scrollIntoView({block:'start', behavior: htmx.config.scrollBehavior});
2606
+                }
2607
+                if (swapSpec.show === "bottom" && (last || target)) {
2608
+                    target = target || last;
2609
+                    target.scrollIntoView({block:'end', behavior: htmx.config.scrollBehavior});
2610
+                }
2611
+            }
2612
+        }
2613
+
2614
+        /**
2615
+         * @param {HTMLElement} elt
2616
+         * @param {string} attr
2617
+         * @param {boolean=} evalAsDefault
2618
+         * @param {Object=} values
2619
+         * @returns {Object}
2620
+         */
2621
+        function getValuesForElement(elt, attr, evalAsDefault, values) {
2622
+            if (values == null) {
2623
+                values = {};
2624
+            }
2625
+            if (elt == null) {
2626
+                return values;
2627
+            }
2628
+            var attributeValue = getAttributeValue(elt, attr);
2629
+            if (attributeValue) {
2630
+                var str = attributeValue.trim();
2631
+                var evaluateValue = evalAsDefault;
2632
+                if (str === "unset") {
2633
+                    return null;
2634
+                }
2635
+                if (str.indexOf("javascript:") === 0) {
2636
+                    str = str.substr(11);
2637
+                    evaluateValue = true;
2638
+                } else if (str.indexOf("js:") === 0) {
2639
+                    str = str.substr(3);
2640
+                    evaluateValue = true;
2641
+                }
2642
+                if (str.indexOf('{') !== 0) {
2643
+                    str = "{" + str + "}";
2644
+                }
2645
+                var varsValues;
2646
+                if (evaluateValue) {
2647
+                    varsValues = maybeEval(elt,function () {return Function("return (" + str + ")")();}, {});
2648
+                } else {
2649
+                    varsValues = parseJSON(str);
2650
+                }
2651
+                for (var key in varsValues) {
2652
+                    if (varsValues.hasOwnProperty(key)) {
2653
+                        if (values[key] == null) {
2654
+                            values[key] = varsValues[key];
2655
+                        }
2656
+                    }
2657
+                }
2658
+            }
2659
+            return getValuesForElement(parentElt(elt), attr, evalAsDefault, values);
2660
+        }
2661
+
2662
+        function maybeEval(elt, toEval, defaultVal) {
2663
+            if (htmx.config.allowEval) {
2664
+                return toEval();
2665
+            } else {
2666
+                triggerErrorEvent(elt, 'htmx:evalDisallowedError');
2667
+                return defaultVal;
2668
+            }
2669
+        }
2670
+
2671
+        /**
2672
+         * @param {HTMLElement} elt
2673
+         * @param {*} expressionVars
2674
+         * @returns
2675
+         */
2676
+        function getHXVarsForElement(elt, expressionVars) {
2677
+            return getValuesForElement(elt, "hx-vars", true, expressionVars);
2678
+        }
2679
+
2680
+        /**
2681
+         * @param {HTMLElement} elt
2682
+         * @param {*} expressionVars
2683
+         * @returns
2684
+         */
2685
+        function getHXValsForElement(elt, expressionVars) {
2686
+            return getValuesForElement(elt, "hx-vals", false, expressionVars);
2687
+        }
2688
+
2689
+        /**
2690
+         * @param {HTMLElement} elt
2691
+         * @returns {Object}
2692
+         */
2693
+        function getExpressionVars(elt) {
2694
+            return mergeObjects(getHXVarsForElement(elt), getHXValsForElement(elt));
2695
+        }
2696
+
2697
+        function safelySetHeaderValue(xhr, header, headerValue) {
2698
+            if (headerValue !== null) {
2699
+                try {
2700
+                    xhr.setRequestHeader(header, headerValue);
2701
+                } catch (e) {
2702
+                    // On an exception, try to set the header URI encoded instead
2703
+                    xhr.setRequestHeader(header, encodeURIComponent(headerValue));
2704
+                    xhr.setRequestHeader(header + "-URI-AutoEncoded", "true");
2705
+                }
2706
+            }
2707
+        }
2708
+
2709
+        function getPathFromResponse(xhr) {
2710
+            // NB: IE11 does not support this stuff
2711
+            if (xhr.responseURL && typeof(URL) !== "undefined") {
2712
+                try {
2713
+                    var url = new URL(xhr.responseURL);
2714
+                    return url.pathname + url.search;
2715
+                } catch (e) {
2716
+                    triggerErrorEvent(getDocument().body, "htmx:badResponseUrl", {url: xhr.responseURL});
2717
+                }
2718
+            }
2719
+        }
2720
+
2721
+        function hasHeader(xhr, regexp) {
2722
+            return xhr.getAllResponseHeaders().match(regexp);
2723
+        }
2724
+
2725
+        function ajaxHelper(verb, path, context) {
2726
+            verb = verb.toLowerCase();
2727
+            if (context) {
2728
+                if (context instanceof Element || isType(context, 'String')) {
2729
+                    return issueAjaxRequest(verb, path, null, null, {
2730
+                        targetOverride: resolveTarget(context),
2731
+                        returnPromise: true
2732
+                    });
2733
+                } else {
2734
+                    return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event,
2735
+                        {
2736
+                            handler : context.handler,
2737
+                            headers : context.headers,
2738
+                            values : context.values,
2739
+                            targetOverride: resolveTarget(context.target),
2740
+                            swapOverride: context.swap,
2741
+                            returnPromise: true
2742
+                        });
2743
+                }
2744
+            } else {
2745
+                return issueAjaxRequest(verb, path, null, null, {
2746
+                        returnPromise: true
2747
+                });
2748
+            }
2749
+        }
2750
+
2751
+        function hierarchyForElt(elt) {
2752
+            var arr = [];
2753
+            while (elt) {
2754
+                arr.push(elt);
2755
+                elt = elt.parentElement;
2756
+            }
2757
+            return arr;
2758
+        }
2759
+
2760
+        function issueAjaxRequest(verb, path, elt, event, etc, confirmed) {
2761
+            var resolve = null;
2762
+            var reject = null;
2763
+            etc = etc != null ? etc : {};
2764
+            if(etc.returnPromise && typeof Promise !== "undefined"){
2765
+                var promise = new Promise(function (_resolve, _reject) {
2766
+                    resolve = _resolve;
2767
+                    reject = _reject;
2768
+                });
2769
+            }
2770
+            if(elt == null) {
2771
+                elt = getDocument().body;
2772
+            }
2773
+            var responseHandler = etc.handler || handleAjaxResponse;
2774
+
2775
+            if (!bodyContains(elt)) {
2776
+                return; // do not issue requests for elements removed from the DOM
2777
+            }
2778
+            var target = etc.targetOverride || getTarget(elt);
2779
+            if (target == null || target == DUMMY_ELT) {
2780
+                triggerErrorEvent(elt, 'htmx:targetError', {target: getAttributeValue(elt, "hx-target")});
2781
+                return;
2782
+            }
2783
+
2784
+            // allow event-based confirmation w/ a callback
2785
+            if (!confirmed) {
2786
+                var issueRequest = function() {
2787
+                    return issueAjaxRequest(verb, path, elt, event, etc, true);
2788
+                }
2789
+                var confirmDetails = {target: target, elt: elt, path: path, verb: verb, triggeringEvent: event, etc: etc, issueRequest: issueRequest};
2790
+                if (triggerEvent(elt, 'htmx:confirm', confirmDetails) === false) {
2791
+                    return;
2792
+                }
2793
+            }
2794
+
2795
+            var syncElt = elt;
2796
+            var eltData = getInternalData(elt);
2797
+            var syncStrategy = getClosestAttributeValue(elt, "hx-sync");
2798
+            var queueStrategy = null;
2799
+            var abortable = false;
2800
+            if (syncStrategy) {
2801
+                var syncStrings = syncStrategy.split(":");
2802
+                var selector = syncStrings[0].trim();
2803
+                if (selector === "this") {
2804
+                    syncElt = findThisElement(elt, 'hx-sync');
2805
+                } else {
2806
+                    syncElt = querySelectorExt(elt, selector);
2807
+                }
2808
+                // default to the drop strategy
2809
+                syncStrategy = (syncStrings[1] || 'drop').trim();
2810
+                eltData = getInternalData(syncElt);
2811
+                if (syncStrategy === "drop" && eltData.xhr && eltData.abortable !== true) {
2812
+                    return;
2813
+                } else if (syncStrategy === "abort") {
2814
+                    if (eltData.xhr) {
2815
+                        return;
2816
+                    } else {
2817
+                        abortable = true;
2818
+                    }
2819
+                } else if (syncStrategy === "replace") {
2820
+                    triggerEvent(syncElt, 'htmx:abort'); // abort the current request and continue
2821
+                } else if (syncStrategy.indexOf("queue") === 0) {
2822
+                    var queueStrArray = syncStrategy.split(" ");
2823
+                    queueStrategy = (queueStrArray[1] || "last").trim();
2824
+                }
2825
+            }
2826
+
2827
+            if (eltData.xhr) {
2828
+                if (eltData.abortable) {
2829
+                    triggerEvent(syncElt, 'htmx:abort'); // abort the current request and continue
2830
+                } else {
2831
+                    if(queueStrategy == null){
2832
+                        if (event) {
2833
+                            var eventData = getInternalData(event);
2834
+                            if (eventData && eventData.triggerSpec && eventData.triggerSpec.queue) {
2835
+                                queueStrategy = eventData.triggerSpec.queue;
2836
+                            }
2837
+                        }
2838
+                        if (queueStrategy == null) {
2839
+                            queueStrategy = "last";
2840
+                        }
2841
+                    }
2842
+                    if (eltData.queuedRequests == null) {
2843
+                        eltData.queuedRequests = [];
2844
+                    }
2845
+                    if (queueStrategy === "first" && eltData.queuedRequests.length === 0) {
2846
+                        eltData.queuedRequests.push(function () {
2847
+                            issueAjaxRequest(verb, path, elt, event, etc)
2848
+                        });
2849
+                    } else if (queueStrategy === "all") {
2850
+                        eltData.queuedRequests.push(function () {
2851
+                            issueAjaxRequest(verb, path, elt, event, etc)
2852
+                        });
2853
+                    } else if (queueStrategy === "last") {
2854
+                        eltData.queuedRequests = []; // dump existing queue
2855
+                        eltData.queuedRequests.push(function () {
2856
+                            issueAjaxRequest(verb, path, elt, event, etc)
2857
+                        });
2858
+                    }
2859
+                    return;
2860
+                }
2861
+            }
2862
+
2863
+            var xhr = new XMLHttpRequest();
2864
+            eltData.xhr = xhr;
2865
+            eltData.abortable = abortable;
2866
+            var endRequestLock = function(){
2867
+                eltData.xhr = null;
2868
+                eltData.abortable = false;
2869
+                if (eltData.queuedRequests != null &&
2870
+                    eltData.queuedRequests.length > 0) {
2871
+                    var queuedRequest = eltData.queuedRequests.shift();
2872
+                    queuedRequest();
2873
+                }
2874
+            }
2875
+            var promptQuestion = getClosestAttributeValue(elt, "hx-prompt");
2876
+            if (promptQuestion) {
2877
+                var promptResponse = prompt(promptQuestion);
2878
+                // prompt returns null if cancelled and empty string if accepted with no entry
2879
+                if (promptResponse === null ||
2880
+                    !triggerEvent(elt, 'htmx:prompt', {prompt: promptResponse, target:target})) {
2881
+                    maybeCall(resolve);
2882
+                    endRequestLock();
2883
+                    return promise;
2884
+                }
2885
+            }
2886
+
2887
+            var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm");
2888
+            if (confirmQuestion) {
2889
+                if(!confirm(confirmQuestion)) {
2890
+                    maybeCall(resolve);
2891
+                    endRequestLock()
2892
+                    return promise;
2893
+                }
2894
+            }
2895
+
2896
+
2897
+            var headers = getHeaders(elt, target, promptResponse);
2898
+            if (etc.headers) {
2899
+                headers = mergeObjects(headers, etc.headers);
2900
+            }
2901
+            var results = getInputValues(elt, verb);
2902
+            var errors = results.errors;
2903
+            var rawParameters = results.values;
2904
+            if (etc.values) {
2905
+                rawParameters = mergeObjects(rawParameters, etc.values);
2906
+            }
2907
+            var expressionVars = getExpressionVars(elt);
2908
+            var allParameters = mergeObjects(rawParameters, expressionVars);
2909
+            var filteredParameters = filterValues(allParameters, elt);
2910
+
2911
+            if (verb !== 'get' && !usesFormData(elt)) {
2912
+                headers['Content-Type'] = 'application/x-www-form-urlencoded';
2913
+            }
2914
+
2915
+            if (htmx.config.getCacheBusterParam && verb === 'get') {
2916
+                filteredParameters['org.htmx.cache-buster'] = getRawAttribute(target, "id") || "true";
2917
+            }
2918
+
2919
+            // behavior of anchors w/ empty href is to use the current URL
2920
+            if (path == null || path === "") {
2921
+                path = getDocument().location.href;
2922
+            }
2923
+
2924
+
2925
+            var requestAttrValues = getValuesForElement(elt, 'hx-request');
2926
+
2927
+            var eltIsBoosted = getInternalData(elt).boosted;
2928
+            var requestConfig = {
2929
+                boosted: eltIsBoosted,
2930
+                parameters: filteredParameters,
2931
+                unfilteredParameters: allParameters,
2932
+                headers:headers,
2933
+                target:target,
2934
+                verb:verb,
2935
+                errors:errors,
2936
+                withCredentials: etc.credentials || requestAttrValues.credentials || htmx.config.withCredentials,
2937
+                timeout:  etc.timeout || requestAttrValues.timeout || htmx.config.timeout,
2938
+                path:path,
2939
+                triggeringEvent:event
2940
+            };
2941
+
2942
+            if(!triggerEvent(elt, 'htmx:configRequest', requestConfig)){
2943
+                maybeCall(resolve);
2944
+                endRequestLock();
2945
+                return promise;
2946
+            }
2947
+
2948
+            // copy out in case the object was overwritten
2949
+            path = requestConfig.path;
2950
+            verb = requestConfig.verb;
2951
+            headers = requestConfig.headers;
2952
+            filteredParameters = requestConfig.parameters;
2953
+            errors = requestConfig.errors;
2954
+
2955
+            if(errors && errors.length > 0){
2956
+                triggerEvent(elt, 'htmx:validation:halted', requestConfig)
2957
+                maybeCall(resolve);
2958
+                endRequestLock();
2959
+                return promise;
2960
+            }
2961
+
2962
+            var splitPath = path.split("#");
2963
+            var pathNoAnchor = splitPath[0];
2964
+            var anchor = splitPath[1];
2965
+            var finalPathForGet = null;
2966
+            if (verb === 'get') {
2967
+                finalPathForGet = pathNoAnchor;
2968
+                var values = Object.keys(filteredParameters).length !== 0;
2969
+                if (values) {
2970
+                    if (finalPathForGet.indexOf("?") < 0) {
2971
+                        finalPathForGet += "?";
2972
+                    } else {
2973
+                        finalPathForGet += "&";
2974
+                    }
2975
+                    finalPathForGet += urlEncode(filteredParameters);
2976
+                    if (anchor) {
2977
+                        finalPathForGet += "#" + anchor;
2978
+                    }
2979
+                }
2980
+                xhr.open('GET', finalPathForGet, true);
2981
+            } else {
2982
+                xhr.open(verb.toUpperCase(), path, true);
2983
+            }
2984
+
2985
+            xhr.overrideMimeType("text/html");
2986
+            xhr.withCredentials = requestConfig.withCredentials;
2987
+            xhr.timeout = requestConfig.timeout;
2988
+
2989
+            // request headers
2990
+            if (requestAttrValues.noHeaders) {
2991
+                // ignore all headers
2992
+            } else {
2993
+                for (var header in headers) {
2994
+                    if (headers.hasOwnProperty(header)) {
2995
+                        var headerValue = headers[header];
2996
+                        safelySetHeaderValue(xhr, header, headerValue);
2997
+                    }
2998
+                }
2999
+            }
3000
+
3001
+            var responseInfo = {
3002
+                xhr: xhr, target: target, requestConfig: requestConfig, etc: etc, boosted: eltIsBoosted,
3003
+                pathInfo: {
3004
+                    requestPath: path,
3005
+                    finalRequestPath: finalPathForGet || path,
3006
+                    anchor: anchor
3007
+                }
3008
+            };
3009
+
3010
+            xhr.onload = function () {
3011
+                try {
3012
+                    var hierarchy = hierarchyForElt(elt);
3013
+                    responseInfo.pathInfo.responsePath = getPathFromResponse(xhr);
3014
+                    responseHandler(elt, responseInfo);
3015
+                    removeRequestIndicatorClasses(indicators);
3016
+                    triggerEvent(elt, 'htmx:afterRequest', responseInfo);
3017
+                    triggerEvent(elt, 'htmx:afterOnLoad', responseInfo);
3018
+                    // if the body no longer contains the element, trigger the event on the closest parent
3019
+                    // remaining in the DOM
3020
+                    if (!bodyContains(elt)) {
3021
+                        var secondaryTriggerElt = null;
3022
+                        while (hierarchy.length > 0 && secondaryTriggerElt == null) {
3023
+                            var parentEltInHierarchy = hierarchy.shift();
3024
+                            if (bodyContains(parentEltInHierarchy)) {
3025
+                                secondaryTriggerElt = parentEltInHierarchy;
3026
+                            }
3027
+                        }
3028
+                        if (secondaryTriggerElt) {
3029
+                            triggerEvent(secondaryTriggerElt, 'htmx:afterRequest', responseInfo);
3030
+                            triggerEvent(secondaryTriggerElt, 'htmx:afterOnLoad', responseInfo);
3031
+                        }
3032
+                    }
3033
+                    maybeCall(resolve);
3034
+                    endRequestLock();
3035
+                } catch (e) {
3036
+                    triggerErrorEvent(elt, 'htmx:onLoadError', mergeObjects({error:e}, responseInfo));
3037
+                    throw e;
3038
+                }
3039
+            }
3040
+            xhr.onerror = function () {
3041
+                removeRequestIndicatorClasses(indicators);
3042
+                triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
3043
+                triggerErrorEvent(elt, 'htmx:sendError', responseInfo);
3044
+                maybeCall(reject);
3045
+                endRequestLock();
3046
+            }
3047
+            xhr.onabort = function() {
3048
+                removeRequestIndicatorClasses(indicators);
3049
+                triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
3050
+                triggerErrorEvent(elt, 'htmx:sendAbort', responseInfo);
3051
+                maybeCall(reject);
3052
+                endRequestLock();
3053
+            }
3054
+            xhr.ontimeout = function() {
3055
+                removeRequestIndicatorClasses(indicators);
3056
+                triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
3057
+                triggerErrorEvent(elt, 'htmx:timeout', responseInfo);
3058
+                maybeCall(reject);
3059
+                endRequestLock();
3060
+            }
3061
+            if(!triggerEvent(elt, 'htmx:beforeRequest', responseInfo)){
3062
+                maybeCall(resolve);
3063
+                endRequestLock()
3064
+                return promise
3065
+            }
3066
+            var indicators = addRequestIndicatorClasses(elt);
3067
+
3068
+            forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) {
3069
+                forEach([xhr, xhr.upload], function (target) {
3070
+                    target.addEventListener(eventName, function(event){
3071
+                        triggerEvent(elt, "htmx:xhr:" + eventName, {
3072
+                            lengthComputable:event.lengthComputable,
3073
+                            loaded:event.loaded,
3074
+                            total:event.total
3075
+                        });
3076
+                    })
3077
+                });
3078
+            });
3079
+            triggerEvent(elt, 'htmx:beforeSend', responseInfo);
3080
+            xhr.send(verb === 'get' ? null : encodeParamsForBody(xhr, elt, filteredParameters));
3081
+            return promise;
3082
+        }
3083
+
3084
+        function determineHistoryUpdates(elt, responseInfo) {
3085
+
3086
+            var xhr = responseInfo.xhr;
3087
+
3088
+            //===========================================
3089
+            // First consult response headers
3090
+            //===========================================
3091
+            var pathFromHeaders = null;
3092
+            var typeFromHeaders = null;
3093
+            if (hasHeader(xhr,/HX-Push:/i)) {
3094
+                pathFromHeaders = xhr.getResponseHeader("HX-Push");
3095
+                typeFromHeaders = "push";
3096
+            } else if (hasHeader(xhr,/HX-Push-Url:/i)) {
3097
+                pathFromHeaders = xhr.getResponseHeader("HX-Push-Url");
3098
+                typeFromHeaders = "push";
3099
+            } else if (hasHeader(xhr,/HX-Replace-Url:/i)) {
3100
+                pathFromHeaders = xhr.getResponseHeader("HX-Replace-Url");
3101
+                typeFromHeaders = "replace";
3102
+            }
3103
+
3104
+            // if there was a response header, that has priority
3105
+            if (pathFromHeaders) {
3106
+                if (pathFromHeaders === "false") {
3107
+                    return {}
3108
+                } else {
3109
+                    return {
3110
+                        type: typeFromHeaders,
3111
+                        path : pathFromHeaders
3112
+                    }
3113
+                }
3114
+            }
3115
+
3116
+            //===========================================
3117
+            // Next resolve via DOM values
3118
+            //===========================================
3119
+            var requestPath =  responseInfo.pathInfo.finalRequestPath;
3120
+            var responsePath =  responseInfo.pathInfo.responsePath;
3121
+
3122
+            var pushUrl = getClosestAttributeValue(elt, "hx-push-url");
3123
+            var replaceUrl = getClosestAttributeValue(elt, "hx-replace-url");
3124
+            var elementIsBoosted = getInternalData(elt).boosted;
3125
+
3126
+            var saveType = null;
3127
+            var path = null;
3128
+
3129
+            if (pushUrl) {
3130
+                saveType = "push";
3131
+                path = pushUrl;
3132
+            } else if (replaceUrl) {
3133
+                saveType = "replace";
3134
+                path = replaceUrl;
3135
+            } else if (elementIsBoosted) {
3136
+                saveType = "push";
3137
+                path = responsePath || requestPath; // if there is no response path, go with the original request path
3138
+            }
3139
+
3140
+            if (path) {
3141
+                // false indicates no push, return empty object
3142
+                if (path === "false") {
3143
+                    return {};
3144
+                }
3145
+
3146
+                // true indicates we want to follow wherever the server ended up sending us
3147
+                if (path === "true") {
3148
+                    path = responsePath || requestPath; // if there is no response path, go with the original request path
3149
+                }
3150
+
3151
+                // restore any anchor associated with the request
3152
+                if (responseInfo.pathInfo.anchor &&
3153
+                    path.indexOf("#") === -1) {
3154
+                    path = path + "#" + responseInfo.pathInfo.anchor;
3155
+                }
3156
+
3157
+                return {
3158
+                    type:saveType,
3159
+                    path: path
3160
+                }
3161
+            } else {
3162
+                return {};
3163
+            }
3164
+        }
3165
+
3166
+        function handleAjaxResponse(elt, responseInfo) {
3167
+            var xhr = responseInfo.xhr;
3168
+            var target = responseInfo.target;
3169
+            var etc = responseInfo.etc;
3170
+
3171
+            if (!triggerEvent(elt, 'htmx:beforeOnLoad', responseInfo)) return;
3172
+
3173
+            if (hasHeader(xhr, /HX-Trigger:/i)) {
3174
+                handleTrigger(xhr, "HX-Trigger", elt);
3175
+            }
3176
+
3177
+            if (hasHeader(xhr, /HX-Location:/i)) {
3178
+                saveCurrentPageToHistory();
3179
+                var redirectPath = xhr.getResponseHeader("HX-Location");
3180
+                var swapSpec;
3181
+                if (redirectPath.indexOf("{") === 0) {
3182
+                    swapSpec = parseJSON(redirectPath);
3183
+                    // what's the best way to throw an error if the user didn't include this
3184
+                    redirectPath = swapSpec['path'];
3185
+                    delete swapSpec['path'];
3186
+                }
3187
+                ajaxHelper('GET', redirectPath, swapSpec).then(function(){
3188
+                    pushUrlIntoHistory(redirectPath);
3189
+                });
3190
+                return;
3191
+            }
3192
+
3193
+            if (hasHeader(xhr, /HX-Redirect:/i)) {
3194
+                location.href = xhr.getResponseHeader("HX-Redirect");
3195
+                return;
3196
+            }
3197
+
3198
+            if (hasHeader(xhr,/HX-Refresh:/i)) {
3199
+                if ("true" === xhr.getResponseHeader("HX-Refresh")) {
3200
+                    location.reload();
3201
+                    return;
3202
+                }
3203
+            }
3204
+
3205
+            if (hasHeader(xhr,/HX-Retarget:/i)) {
3206
+                responseInfo.target = getDocument().querySelector(xhr.getResponseHeader("HX-Retarget"));
3207
+            }
3208
+
3209
+            var historyUpdate = determineHistoryUpdates(elt, responseInfo);
3210
+
3211
+            // by default htmx only swaps on 200 return codes and does not swap
3212
+            // on 204 'No Content'
3213
+            // this can be ovverriden by responding to the htmx:beforeSwap event and
3214
+            // overriding the detail.shouldSwap property
3215
+            var shouldSwap = xhr.status >= 200 && xhr.status < 400 && xhr.status !== 204;
3216
+            var serverResponse = xhr.response;
3217
+            var isError = xhr.status >= 400;
3218
+            var beforeSwapDetails = mergeObjects({shouldSwap: shouldSwap, serverResponse:serverResponse, isError:isError}, responseInfo);
3219
+            if (!triggerEvent(target, 'htmx:beforeSwap', beforeSwapDetails)) return;
3220
+
3221
+            target = beforeSwapDetails.target; // allow re-targeting
3222
+            serverResponse = beforeSwapDetails.serverResponse; // allow updating content
3223
+            isError = beforeSwapDetails.isError; // allow updating error
3224
+
3225
+            responseInfo.target = target; // Make updated target available to response events
3226
+            responseInfo.failed = isError; // Make failed property available to response events
3227
+            responseInfo.successful = !isError; // Make successful property available to response events
3228
+
3229
+            if (beforeSwapDetails.shouldSwap) {
3230
+                if (xhr.status === 286) {
3231
+                    cancelPolling(elt);
3232
+                }
3233
+
3234
+                withExtensions(elt, function (extension) {
3235
+                    serverResponse = extension.transformResponse(serverResponse, xhr, elt);
3236
+                });
3237
+
3238
+                // Save current page if there will be a history update
3239
+                if (historyUpdate.type) {
3240
+                    saveCurrentPageToHistory();
3241
+                }
3242
+
3243
+                var swapOverride = etc.swapOverride;
3244
+                if (hasHeader(xhr,/HX-Reswap:/i)) {
3245
+                    swapOverride = xhr.getResponseHeader("HX-Reswap");
3246
+                }
3247
+                var swapSpec = getSwapSpecification(elt, swapOverride);
3248
+
3249
+                target.classList.add(htmx.config.swappingClass);
3250
+
3251
+                // optional transition API promise callbacks
3252
+                var settleResolve = null;
3253
+                var settleReject = null;
3254
+
3255
+                var doSwap = function () {
3256
+                    try {
3257
+                        var activeElt = document.activeElement;
3258
+                        var selectionInfo = {};
3259
+                        try {
3260
+                            selectionInfo = {
3261
+                                elt: activeElt,
3262
+                                // @ts-ignore
3263
+                                start: activeElt ? activeElt.selectionStart : null,
3264
+                                // @ts-ignore
3265
+                                end: activeElt ? activeElt.selectionEnd : null
3266
+                            };
3267
+                        } catch (e) {
3268
+                            // safari issue - see https://github.com/microsoft/playwright/issues/5894
3269
+                        }
3270
+
3271
+                        var settleInfo = makeSettleInfo(target);
3272
+                        selectAndSwap(swapSpec.swapStyle, target, elt, serverResponse, settleInfo);
3273
+
3274
+                        if (selectionInfo.elt &&
3275
+                            !bodyContains(selectionInfo.elt) &&
3276
+                            selectionInfo.elt.id) {
3277
+                            var newActiveElt = document.getElementById(selectionInfo.elt.id);
3278
+                            var focusOptions = { preventScroll: swapSpec.focusScroll !== undefined ? !swapSpec.focusScroll : !htmx.config.defaultFocusScroll };
3279
+                            if (newActiveElt) {
3280
+                                // @ts-ignore
3281
+                                if (selectionInfo.start && newActiveElt.setSelectionRange) {
3282
+                                    // @ts-ignore
3283
+                                    try {
3284
+                                        newActiveElt.setSelectionRange(selectionInfo.start, selectionInfo.end);
3285
+                                    } catch (e) {
3286
+                                        // the setSelectionRange method is present on fields that don't support it, so just let this fail
3287
+                                    }
3288
+                                }
3289
+                                newActiveElt.focus(focusOptions);
3290
+                            }
3291
+                        }
3292
+
3293
+                        target.classList.remove(htmx.config.swappingClass);
3294
+                        forEach(settleInfo.elts, function (elt) {
3295
+                            if (elt.classList) {
3296
+                                elt.classList.add(htmx.config.settlingClass);
3297
+                            }
3298
+                            triggerEvent(elt, 'htmx:afterSwap', responseInfo);
3299
+                        });
3300
+
3301
+                        if (hasHeader(xhr, /HX-Trigger-After-Swap:/i)) {
3302
+                            var finalElt = elt;
3303
+                            if (!bodyContains(elt)) {
3304
+                                finalElt = getDocument().body;
3305
+                            }
3306
+                            handleTrigger(xhr, "HX-Trigger-After-Swap", finalElt);
3307
+                        }
3308
+
3309
+                        var doSettle = function () {
3310
+                            forEach(settleInfo.tasks, function (task) {
3311
+                                task.call();
3312
+                            });
3313
+                            forEach(settleInfo.elts, function (elt) {
3314
+                                if (elt.classList) {
3315
+                                    elt.classList.remove(htmx.config.settlingClass);
3316
+                                }
3317
+                                triggerEvent(elt, 'htmx:afterSettle', responseInfo);
3318
+                            });
3319
+
3320
+                            // if we need to save history, do so
3321
+                            if (historyUpdate.type) {
3322
+                                if (historyUpdate.type === "push") {
3323
+                                    pushUrlIntoHistory(historyUpdate.path);
3324
+                                    triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', {path: historyUpdate.path});
3325
+                                } else {
3326
+                                    replaceUrlInHistory(historyUpdate.path);
3327
+                                    triggerEvent(getDocument().body, 'htmx:replacedInHistory', {path: historyUpdate.path});
3328
+                                }
3329
+                            }
3330
+                            if (responseInfo.pathInfo.anchor) {
3331
+                                var anchorTarget = find("#" + responseInfo.pathInfo.anchor);
3332
+                                if(anchorTarget) {
3333
+                                    anchorTarget.scrollIntoView({block:'start', behavior: "auto"});
3334
+                                }
3335
+                            }
3336
+
3337
+                            if(settleInfo.title) {
3338
+                                var titleElt = find("title");
3339
+                                if(titleElt) {
3340
+                                    titleElt.innerHTML = settleInfo.title;
3341
+                                } else {
3342
+                                    window.document.title = settleInfo.title;
3343
+                                }
3344
+                            }
3345
+
3346
+                            updateScrollState(settleInfo.elts, swapSpec);
3347
+
3348
+                            if (hasHeader(xhr, /HX-Trigger-After-Settle:/i)) {
3349
+                                var finalElt = elt;
3350
+                                if (!bodyContains(elt)) {
3351
+                                    finalElt = getDocument().body;
3352
+                                }
3353
+                                handleTrigger(xhr, "HX-Trigger-After-Settle", finalElt);
3354
+                            }
3355
+                            maybeCall(settleResolve);
3356
+                        }
3357
+
3358
+                        if (swapSpec.settleDelay > 0) {
3359
+                            setTimeout(doSettle, swapSpec.settleDelay)
3360
+                        } else {
3361
+                            doSettle();
3362
+                        }
3363
+                    } catch (e) {
3364
+                        triggerErrorEvent(elt, 'htmx:swapError', responseInfo);
3365
+                        maybeCall(settleReject);
3366
+                        throw e;
3367
+                    }
3368
+                };
3369
+
3370
+                var shouldTransition = htmx.config.globalViewTransitions
3371
+                if(swapSpec.hasOwnProperty('transition')){
3372
+                    shouldTransition = swapSpec.transition;
3373
+                }
3374
+
3375
+                if(shouldTransition &&
3376
+                    triggerEvent(elt, 'htmx:beforeTransition', responseInfo) &&
3377
+                    typeof Promise !== "undefined" && document.startViewTransition){
3378
+                    var settlePromise = new Promise(function (_resolve, _reject) {
3379
+                        settleResolve = _resolve;
3380
+                        settleReject = _reject;
3381
+                    });
3382
+                    // wrap the original doSwap() in a call to startViewTransition()
3383
+                    var innerDoSwap = doSwap;
3384
+                    doSwap = function() {
3385
+                        document.startViewTransition(function () {
3386
+                            innerDoSwap();
3387
+                            return settlePromise;
3388
+                        });
3389
+                    }
3390
+                }
3391
+
3392
+
3393
+                if (swapSpec.swapDelay > 0) {
3394
+                    setTimeout(doSwap, swapSpec.swapDelay)
3395
+                } else {
3396
+                    doSwap();
3397
+                }
3398
+            }
3399
+            if (isError) {
3400
+                triggerErrorEvent(elt, 'htmx:responseError', mergeObjects({error: "Response Status Error Code " + xhr.status + " from " + responseInfo.pathInfo.requestPath}, responseInfo));
3401
+            }
3402
+        }
3403
+
3404
+        //====================================================================
3405
+        // Extensions API
3406
+        //====================================================================
3407
+
3408
+        /** @type {Object<string, import("./htmx").HtmxExtension>} */
3409
+        var extensions = {};
3410
+
3411
+        /**
3412
+         * extensionBase defines the default functions for all extensions.
3413
+         * @returns {import("./htmx").HtmxExtension}
3414
+         */
3415
+        function extensionBase() {
3416
+            return {
3417
+                init: function(api) {return null;},
3418
+                onEvent : function(name, evt) {return true;},
3419
+                transformResponse : function(text, xhr, elt) {return text;},
3420
+                isInlineSwap : function(swapStyle) {return false;},
3421
+                handleSwap : function(swapStyle, target, fragment, settleInfo) {return false;},
3422
+                encodeParameters : function(xhr, parameters, elt) {return null;}
3423
+            }
3424
+        }
3425
+
3426
+        /**
3427
+         * defineExtension initializes the extension and adds it to the htmx registry
3428
+         *
3429
+         * @param {string} name
3430
+         * @param {import("./htmx").HtmxExtension} extension
3431
+         */
3432
+        function defineExtension(name, extension) {
3433
+            if(extension.init) {
3434
+                extension.init(internalAPI)
3435
+            }
3436
+            extensions[name] = mergeObjects(extensionBase(), extension);
3437
+        }
3438
+
3439
+        /**
3440
+         * removeExtension removes an extension from the htmx registry
3441
+         *
3442
+         * @param {string} name
3443
+         */
3444
+        function removeExtension(name) {
3445
+            delete extensions[name];
3446
+        }
3447
+
3448
+        /**
3449
+         * getExtensions searches up the DOM tree to return all extensions that can be applied to a given element
3450
+         *
3451
+         * @param {HTMLElement} elt
3452
+         * @param {import("./htmx").HtmxExtension[]=} extensionsToReturn
3453
+         * @param {import("./htmx").HtmxExtension[]=} extensionsToIgnore
3454
+         */
3455
+         function getExtensions(elt, extensionsToReturn, extensionsToIgnore) {
3456
+
3457
+            if (elt == undefined) {
3458
+                return extensionsToReturn;
3459
+            }
3460
+            if (extensionsToReturn == undefined) {
3461
+                extensionsToReturn = [];
3462
+            }
3463
+            if (extensionsToIgnore == undefined) {
3464
+                extensionsToIgnore = [];
3465
+            }
3466
+            var extensionsForElement = getAttributeValue(elt, "hx-ext");
3467
+            if (extensionsForElement) {
3468
+                forEach(extensionsForElement.split(","), function(extensionName){
3469
+                    extensionName = extensionName.replace(/ /g, '');
3470
+                    if (extensionName.slice(0, 7) == "ignore:") {
3471
+                        extensionsToIgnore.push(extensionName.slice(7));
3472
+                        return;
3473
+                    }
3474
+                    if (extensionsToIgnore.indexOf(extensionName) < 0) {
3475
+                        var extension = extensions[extensionName];
3476
+                        if (extension && extensionsToReturn.indexOf(extension) < 0) {
3477
+                            extensionsToReturn.push(extension);
3478
+                        }
3479
+                    }
3480
+                });
3481
+            }
3482
+            return getExtensions(parentElt(elt), extensionsToReturn, extensionsToIgnore);
3483
+        }
3484
+
3485
+        //====================================================================
3486
+        // Initialization
3487
+        //====================================================================
3488
+
3489
+        function ready(fn) {
3490
+            if (getDocument().readyState !== 'loading') {
3491
+                fn();
3492
+            } else {
3493
+                getDocument().addEventListener('DOMContentLoaded', fn);
3494
+            }
3495
+        }
3496
+
3497
+        function insertIndicatorStyles() {
3498
+            if (htmx.config.includeIndicatorStyles !== false) {
3499
+                getDocument().head.insertAdjacentHTML("beforeend",
3500
+                    "<style>\
3501
+                      ." + htmx.config.indicatorClass + "{opacity:0;transition: opacity 200ms ease-in;}\
3502
+                      ." + htmx.config.requestClass + " ." + htmx.config.indicatorClass + "{opacity:1}\
3503
+                      ." + htmx.config.requestClass + "." + htmx.config.indicatorClass + "{opacity:1}\
3504
+                    </style>");
3505
+            }
3506
+        }
3507
+
3508
+        function getMetaConfig() {
3509
+            var element = getDocument().querySelector('meta[name="htmx-config"]');
3510
+            if (element) {
3511
+                // @ts-ignore
3512
+                return parseJSON(element.content);
3513
+            } else {
3514
+                return null;
3515
+            }
3516
+        }
3517
+
3518
+        function mergeMetaConfig() {
3519
+            var metaConfig = getMetaConfig();
3520
+            if (metaConfig) {
3521
+                htmx.config = mergeObjects(htmx.config , metaConfig)
3522
+            }
3523
+        }
3524
+
3525
+        // initialize the document
3526
+        ready(function () {
3527
+            mergeMetaConfig();
3528
+            insertIndicatorStyles();
3529
+            var body = getDocument().body;
3530
+            processNode(body);
3531
+            var restoredElts = getDocument().querySelectorAll(
3532
+                "[hx-trigger='restored'],[data-hx-trigger='restored']"
3533
+            );
3534
+            body.addEventListener("htmx:abort", function (evt) {
3535
+                var target = evt.target;
3536
+                var internalData = getInternalData(target);
3537
+                if (internalData && internalData.xhr) {
3538
+                    internalData.xhr.abort();
3539
+                }
3540
+            });
3541
+            var originalPopstate = window.onpopstate;
3542
+            window.onpopstate = function (event) {
3543
+                if (event.state && event.state.htmx) {
3544
+                    restoreHistory();
3545
+                    forEach(restoredElts, function(elt){
3546
+                        triggerEvent(elt, 'htmx:restored', {
3547
+                            'document': getDocument(),
3548
+                            'triggerEvent': triggerEvent
3549
+                        });
3550
+                    });
3551
+                } else {
3552
+                    if (originalPopstate) {
3553
+                        originalPopstate(event);
3554
+                    }
3555
+                }
3556
+            };
3557
+            setTimeout(function () {
3558
+                triggerEvent(body, 'htmx:load', {}); // give ready handlers a chance to load up before firing this event
3559
+                body = null; // kill reference for gc
3560
+            }, 0);
3561
+        })
3562
+
3563
+        return htmx;
3564
+    }
3565
+)()
3566
+}));
0 3567
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+(function(e,t){if(typeof define==="function"&&define.amd){define([],t)}else if(typeof module==="object"&&module.exports){module.exports=t()}else{e.htmx=e.htmx||t()}})(typeof self!=="undefined"?self:this,function(){return function(){"use strict";var z={onLoad:t,process:Tt,on:le,off:ue,trigger:ie,ajax:dr,find:b,findAll:f,closest:d,values:function(e,t){var r=Jt(e,t||"post");return r.values},remove:B,addClass:j,removeClass:n,toggleClass:U,takeClass:V,defineExtension:yr,removeExtension:br,logAll:F,logger:null,config:{historyEnabled:true,historyCacheSize:10,refreshOnHistoryMiss:false,defaultSwapStyle:"innerHTML",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:true,indicatorClass:"htmx-indicator",requestClass:"htmx-request",addedClass:"htmx-added",settlingClass:"htmx-settling",swappingClass:"htmx-swapping",allowEval:true,inlineScriptNonce:"",attributesToSettle:["class","style","width","height"],withCredentials:false,timeout:0,wsReconnectDelay:"full-jitter",wsBinaryType:"blob",disableSelector:"[hx-disable], [data-hx-disable]",useTemplateFragments:false,scrollBehavior:"smooth",defaultFocusScroll:false,getCacheBusterParam:false,globalViewTransitions:false},parseInterval:v,_:e,createEventSource:function(e){return new EventSource(e,{withCredentials:true})},createWebSocket:function(e){var t=new WebSocket(e,[]);t.binaryType=z.config.wsBinaryType;return t},version:"1.9.2"};var C={addTriggerHandler:xt,bodyContains:ee,canAccessLocalStorage:D,filterValues:er,hasAttribute:q,getAttributeValue:G,getClosestMatch:c,getExpressionVars:fr,getHeaders:Qt,getInputValues:Jt,getInternalData:Y,getSwapSpecification:rr,getTriggerSpecs:ze,getTarget:de,makeFragment:l,mergeObjects:te,makeSettleInfo:S,oobSwap:me,selectAndSwap:Me,settleImmediately:Bt,shouldCancel:Ke,triggerEvent:ie,triggerErrorEvent:ne,withExtensions:w};var R=["get","post","put","delete","patch"];var O=R.map(function(e){return"[hx-"+e+"], [data-hx-"+e+"]"}).join(", ");function v(e){if(e==undefined){return undefined}if(e.slice(-2)=="ms"){return parseFloat(e.slice(0,-2))||undefined}if(e.slice(-1)=="s"){return parseFloat(e.slice(0,-1))*1e3||undefined}if(e.slice(-1)=="m"){return parseFloat(e.slice(0,-1))*1e3*60||undefined}return parseFloat(e)||undefined}function $(e,t){return e.getAttribute&&e.getAttribute(t)}function q(e,t){return e.hasAttribute&&(e.hasAttribute(t)||e.hasAttribute("data-"+t))}function G(e,t){return $(e,t)||$(e,"data-"+t)}function u(e){return e.parentElement}function J(){return document}function c(e,t){while(e&&!t(e)){e=u(e)}return e?e:null}function T(e,t,r){var n=G(t,r);var i=G(t,"hx-disinherit");if(e!==t&&i&&(i==="*"||i.split(" ").indexOf(r)>=0)){return"unset"}else{return n}}function Z(t,r){var n=null;c(t,function(e){return n=T(t,e,r)});if(n!=="unset"){return n}}function h(e,t){var r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector;return r&&r.call(e,t)}function H(e){var t=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i;var r=t.exec(e);if(r){return r[1].toLowerCase()}else{return""}}function i(e,t){var r=new DOMParser;var n=r.parseFromString(e,"text/html");var i=n.body;while(t>0){t--;i=i.firstChild}if(i==null){i=J().createDocumentFragment()}return i}function L(e){return e.match(/<body/)}function l(e){var t=!L(e);if(z.config.useTemplateFragments&&t){var r=i("<body><template>"+e+"</template></body>",0);return r.querySelector("template").content}else{var n=H(e);switch(n){case"thead":case"tbody":case"tfoot":case"colgroup":case"caption":return i("<table>"+e+"</table>",1);case"col":return i("<table><colgroup>"+e+"</colgroup></table>",2);case"tr":return i("<table><tbody>"+e+"</tbody></table>",2);case"td":case"th":return i("<table><tbody><tr>"+e+"</tr></tbody></table>",3);case"script":return i("<div>"+e+"</div>",1);default:return i(e,0)}}}function K(e){if(e){e()}}function A(e,t){return Object.prototype.toString.call(e)==="[object "+t+"]"}function N(e){return A(e,"Function")}function I(e){return A(e,"Object")}function Y(e){var t="htmx-internal-data";var r=e[t];if(!r){r=e[t]={}}return r}function k(e){var t=[];if(e){for(var r=0;r<e.length;r++){t.push(e[r])}}return t}function Q(e,t){if(e){for(var r=0;r<e.length;r++){t(e[r])}}}function P(e){var t=e.getBoundingClientRect();var r=t.top;var n=t.bottom;return r<window.innerHeight&&n>=0}function ee(e){if(e.getRootNode&&e.getRootNode()instanceof ShadowRoot){return J().body.contains(e.getRootNode().host)}else{return J().body.contains(e)}}function M(e){return e.trim().split(/\s+/)}function te(e,t){for(var r in t){if(t.hasOwnProperty(r)){e[r]=t[r]}}return e}function y(e){try{return JSON.parse(e)}catch(e){x(e);return null}}function D(){var e="htmx:localStorageTest";try{localStorage.setItem(e,e);localStorage.removeItem(e);return true}catch(e){return false}}function X(t){try{var e=new URL(t);if(e){t=e.pathname+e.search}if(!t.match("^/$")){t=t.replace(/\/+$/,"")}return t}catch(e){return t}}function e(e){return sr(J().body,function(){return eval(e)})}function t(t){var e=z.on("htmx:load",function(e){t(e.detail.elt)});return e}function F(){z.logger=function(e,t,r){if(console){console.log(t,e,r)}}}function b(e,t){if(t){return e.querySelector(t)}else{return b(J(),e)}}function f(e,t){if(t){return e.querySelectorAll(t)}else{return f(J(),e)}}function B(e,t){e=s(e);if(t){setTimeout(function(){B(e);e=null},t)}else{e.parentElement.removeChild(e)}}function j(e,t,r){e=s(e);if(r){setTimeout(function(){j(e,t);e=null},r)}else{e.classList&&e.classList.add(t)}}function n(e,t,r){e=s(e);if(r){setTimeout(function(){n(e,t);e=null},r)}else{if(e.classList){e.classList.remove(t);if(e.classList.length===0){e.removeAttribute("class")}}}}function U(e,t){e=s(e);e.classList.toggle(t)}function V(e,t){e=s(e);Q(e.parentElement.children,function(e){n(e,t)});j(e,t)}function d(e,t){e=s(e);if(e.closest){return e.closest(t)}else{do{if(e==null||h(e,t)){return e}}while(e=e&&u(e));return null}}function r(e){var t=e.trim();if(t.startsWith("<")&&t.endsWith("/>")){return t.substring(1,t.length-2)}else{return t}}function _(e,t){if(t.indexOf("closest ")===0){return[d(e,r(t.substr(8)))]}else if(t.indexOf("find ")===0){return[b(e,r(t.substr(5)))]}else if(t.indexOf("next ")===0){return[W(e,r(t.substr(5)))]}else if(t.indexOf("previous ")===0){return[oe(e,r(t.substr(9)))]}else if(t==="document"){return[document]}else if(t==="window"){return[window]}else{return J().querySelectorAll(r(t))}}var W=function(e,t){var r=J().querySelectorAll(t);for(var n=0;n<r.length;n++){var i=r[n];if(i.compareDocumentPosition(e)===Node.DOCUMENT_POSITION_PRECEDING){return i}}};var oe=function(e,t){var r=J().querySelectorAll(t);for(var n=r.length-1;n>=0;n--){var i=r[n];if(i.compareDocumentPosition(e)===Node.DOCUMENT_POSITION_FOLLOWING){return i}}};function re(e,t){if(t){return _(e,t)[0]}else{return _(J().body,e)[0]}}function s(e){if(A(e,"String")){return b(e)}else{return e}}function se(e,t,r){if(N(t)){return{target:J().body,event:e,listener:t}}else{return{target:s(e),event:t,listener:r}}}function le(t,r,n){Sr(function(){var e=se(t,r,n);e.target.addEventListener(e.event,e.listener)});var e=N(r);return e?r:n}function ue(t,r,n){Sr(function(){var e=se(t,r,n);e.target.removeEventListener(e.event,e.listener)});return N(r)?r:n}var fe=J().createElement("output");function ce(e,t){var r=Z(e,t);if(r){if(r==="this"){return[he(e,t)]}else{var n=_(e,r);if(n.length===0){x('The selector "'+r+'" on '+t+" returned no matches!");return[fe]}else{return n}}}}function he(e,t){return c(e,function(e){return G(e,t)!=null})}function de(e){var t=Z(e,"hx-target");if(t){if(t==="this"){return he(e,"hx-target")}else{return re(e,t)}}else{var r=Y(e);if(r.boosted){return J().body}else{return e}}}function ve(e){var t=z.config.attributesToSettle;for(var r=0;r<t.length;r++){if(e===t[r]){return true}}return false}function ge(t,r){Q(t.attributes,function(e){if(!r.hasAttribute(e.name)&&ve(e.name)){t.removeAttribute(e.name)}});Q(r.attributes,function(e){if(ve(e.name)){t.setAttribute(e.name,e.value)}})}function pe(e,t){var r=wr(t);for(var n=0;n<r.length;n++){var i=r[n];try{if(i.isInlineSwap(e)){return true}}catch(e){x(e)}}return e==="outerHTML"}function me(e,i,a){var t="#"+i.id;var o="outerHTML";if(e==="true"){}else if(e.indexOf(":")>0){o=e.substr(0,e.indexOf(":"));t=e.substr(e.indexOf(":")+1,e.length)}else{o=e}var r=J().querySelectorAll(t);if(r){Q(r,function(e){var t;var r=i.cloneNode(true);t=J().createDocumentFragment();t.appendChild(r);if(!pe(o,e)){t=r}var n={shouldSwap:true,target:e,fragment:t};if(!ie(e,"htmx:oobBeforeSwap",n))return;e=n.target;if(n["shouldSwap"]){ke(o,e,e,t,a)}Q(a.elts,function(e){ie(e,"htmx:oobAfterSwap",n)})});i.parentNode.removeChild(i)}else{i.parentNode.removeChild(i);ne(J().body,"htmx:oobErrorNoTarget",{content:i})}return e}function xe(e,t,r){var n=Z(e,"hx-select-oob");if(n){var i=n.split(",");for(let e=0;e<i.length;e++){var a=i[e].split(":",2);var o=a[0].trim();if(o.indexOf("#")===0){o=o.substring(1)}var s=a[1]||"true";var l=t.querySelector("#"+o);if(l){me(s,l,r)}}}Q(f(t,"[hx-swap-oob], [data-hx-swap-oob]"),function(e){var t=G(e,"hx-swap-oob");if(t!=null){me(t,e,r)}})}function ye(e){Q(f(e,"[hx-preserve], [data-hx-preserve]"),function(e){var t=G(e,"id");var r=J().getElementById(t);if(r!=null){e.parentNode.replaceChild(r,e)}})}function be(a,e,o){Q(e.querySelectorAll("[id]"),function(e){if(e.id&&e.id.length>0){var t=e.id.replace("'","\\'");var r=e.tagName.replace(":","\\:");var n=a.querySelector(r+"[id='"+t+"']");if(n&&n!==a){var i=e.cloneNode();ge(e,n);o.tasks.push(function(){ge(e,i)})}}})}function we(e){return function(){n(e,z.config.addedClass);Tt(e);bt(e);Se(e);ie(e,"htmx:load")}}function Se(e){var t="[autofocus]";var r=h(e,t)?e:e.querySelector(t);if(r!=null){r.focus()}}function a(e,t,r,n){be(e,r,n);while(r.childNodes.length>0){var i=r.firstChild;j(i,z.config.addedClass);e.insertBefore(i,t);if(i.nodeType!==Node.TEXT_NODE&&i.nodeType!==Node.COMMENT_NODE){n.tasks.push(we(i))}}}function Ee(e,t){var r=0;while(r<e.length){t=(t<<5)-t+e.charCodeAt(r++)|0}return t}function Ce(e){var t=0;if(e.attributes){for(var r=0;r<e.attributes.length;r++){var n=e.attributes[r];if(n.value){t=Ee(n.name,t);t=Ee(n.value,t)}}}return t}function Re(t){var r=Y(t);if(r.timeout){clearTimeout(r.timeout)}if(r.webSocket){r.webSocket.close()}if(r.sseEventSource){r.sseEventSource.close()}if(r.listenerInfos){Q(r.listenerInfos,function(e){if(e.on){e.on.removeEventListener(e.trigger,e.listener)}})}if(r.onHandlers){for(let e=0;e<r.onHandlers.length;e++){const n=r.onHandlers[e];t.removeEventListener(n.name,n.handler)}}}function o(e){ie(e,"htmx:beforeCleanupElement");Re(e);if(e.children){Q(e.children,function(e){o(e)})}}function Oe(e,t,r){if(e.tagName==="BODY"){return Ne(e,t,r)}else{var n;var i=e.previousSibling;a(u(e),e,t,r);if(i==null){n=u(e).firstChild}else{n=i.nextSibling}Y(e).replacedWith=n;r.elts=[];while(n&&n!==e){if(n.nodeType===Node.ELEMENT_NODE){r.elts.push(n)}n=n.nextElementSibling}o(e);u(e).removeChild(e)}}function qe(e,t,r){return a(e,e.firstChild,t,r)}function Te(e,t,r){return a(u(e),e,t,r)}function He(e,t,r){return a(e,null,t,r)}function Le(e,t,r){return a(u(e),e.nextSibling,t,r)}function Ae(e,t,r){o(e);return u(e).removeChild(e)}function Ne(e,t,r){var n=e.firstChild;a(e,n,t,r);if(n){while(n.nextSibling){o(n.nextSibling);e.removeChild(n.nextSibling)}o(n);e.removeChild(n)}}function Ie(e,t){var r=Z(e,"hx-select");if(r){var n=J().createDocumentFragment();Q(t.querySelectorAll(r),function(e){n.appendChild(e)});t=n}return t}function ke(e,t,r,n,i){switch(e){case"none":return;case"outerHTML":Oe(r,n,i);return;case"afterbegin":qe(r,n,i);return;case"beforebegin":Te(r,n,i);return;case"beforeend":He(r,n,i);return;case"afterend":Le(r,n,i);return;case"delete":Ae(r,n,i);return;default:var a=wr(t);for(var o=0;o<a.length;o++){var s=a[o];try{var l=s.handleSwap(e,r,n,i);if(l){if(typeof l.length!=="undefined"){for(var u=0;u<l.length;u++){var f=l[u];if(f.nodeType!==Node.TEXT_NODE&&f.nodeType!==Node.COMMENT_NODE){i.tasks.push(we(f))}}}return}}catch(e){x(e)}}if(e==="innerHTML"){Ne(r,n,i)}else{ke(z.config.defaultSwapStyle,t,r,n,i)}}}function Pe(e){if(e.indexOf("<title")>-1){var t=e.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim,"");var r=t.match(/<title(\s[^>]*>|>)([\s\S]*?)<\/title>/im);if(r){return r[2]}}}function Me(e,t,r,n,i){i.title=Pe(n);var a=l(n);if(a){xe(r,a,i);a=Ie(r,a);ye(a);return ke(e,r,t,a,i)}}function De(e,t,r){var n=e.getResponseHeader(t);if(n.indexOf("{")===0){var i=y(n);for(var a in i){if(i.hasOwnProperty(a)){var o=i[a];if(!I(o)){o={value:o}}ie(r,a,o)}}}else{ie(r,n,[])}}var Xe=/\s/;var g=/[\s,]/;var Fe=/[_$a-zA-Z]/;var Be=/[_$a-zA-Z0-9]/;var je=['"',"'","/"];var p=/[^\s]/;function Ue(e){var t=[];var r=0;while(r<e.length){if(Fe.exec(e.charAt(r))){var n=r;while(Be.exec(e.charAt(r+1))){r++}t.push(e.substr(n,r-n+1))}else if(je.indexOf(e.charAt(r))!==-1){var i=e.charAt(r);var n=r;r++;while(r<e.length&&e.charAt(r)!==i){if(e.charAt(r)==="\\"){r++}r++}t.push(e.substr(n,r-n+1))}else{var a=e.charAt(r);t.push(a)}r++}return t}function Ve(e,t,r){return Fe.exec(e.charAt(0))&&e!=="true"&&e!=="false"&&e!=="this"&&e!==r&&t!=="."}function _e(e,t,r){if(t[0]==="["){t.shift();var n=1;var i=" return (function("+r+"){ return (";var a=null;while(t.length>0){var o=t[0];if(o==="]"){n--;if(n===0){if(a===null){i=i+"true"}t.shift();i+=")})";try{var s=sr(e,function(){return Function(i)()},function(){return true});s.source=i;return s}catch(e){ne(J().body,"htmx:syntax:error",{error:e,source:i});return null}}}else if(o==="["){n++}if(Ve(o,a,r)){i+="(("+r+"."+o+") ? ("+r+"."+o+") : (window."+o+"))"}else{i=i+o}a=t.shift()}}}function m(e,t){var r="";while(e.length>0&&!e[0].match(t)){r+=e.shift()}return r}var We="input, textarea, select";function ze(e){var t=G(e,"hx-trigger");var r=[];if(t){var n=Ue(t);do{m(n,p);var i=n.length;var a=m(n,/[,\[\s]/);if(a!==""){if(a==="every"){var o={trigger:"every"};m(n,p);o.pollInterval=v(m(n,/[,\[\s]/));m(n,p);var s=_e(e,n,"event");if(s){o.eventFilter=s}r.push(o)}else if(a.indexOf("sse:")===0){r.push({trigger:"sse",sseEvent:a.substr(4)})}else{var l={trigger:a};var s=_e(e,n,"event");if(s){l.eventFilter=s}while(n.length>0&&n[0]!==","){m(n,p);var u=n.shift();if(u==="changed"){l.changed=true}else if(u==="once"){l.once=true}else if(u==="consume"){l.consume=true}else if(u==="delay"&&n[0]===":"){n.shift();l.delay=v(m(n,g))}else if(u==="from"&&n[0]===":"){n.shift();var f=m(n,g);if(f==="closest"||f==="find"||f==="next"||f==="previous"){n.shift();f+=" "+m(n,g)}l.from=f}else if(u==="target"&&n[0]===":"){n.shift();l.target=m(n,g)}else if(u==="throttle"&&n[0]===":"){n.shift();l.throttle=v(m(n,g))}else if(u==="queue"&&n[0]===":"){n.shift();l.queue=m(n,g)}else if((u==="root"||u==="threshold")&&n[0]===":"){n.shift();l[u]=m(n,g)}else{ne(e,"htmx:syntax:error",{token:n.shift()})}}r.push(l)}}if(n.length===i){ne(e,"htmx:syntax:error",{token:n.shift()})}m(n,p)}while(n[0]===","&&n.shift())}if(r.length>0){return r}else if(h(e,"form")){return[{trigger:"submit"}]}else if(h(e,'input[type="button"]')){return[{trigger:"click"}]}else if(h(e,We)){return[{trigger:"change"}]}else{return[{trigger:"click"}]}}function $e(e){Y(e).cancelled=true}function Ge(e,t,r){var n=Y(e);n.timeout=setTimeout(function(){if(ee(e)&&n.cancelled!==true){if(!Qe(r,Lt("hx:poll:trigger",{triggerSpec:r,target:e}))){t(e)}Ge(e,t,r)}},r.pollInterval)}function Je(e){return location.hostname===e.hostname&&$(e,"href")&&$(e,"href").indexOf("#")!==0}function Ze(t,r,e){if(t.tagName==="A"&&Je(t)&&(t.target===""||t.target==="_self")||t.tagName==="FORM"){r.boosted=true;var n,i;if(t.tagName==="A"){n="get";i=t.href}else{var a=$(t,"method");n=a?a.toLowerCase():"get";if(n==="get"){}i=$(t,"action")}e.forEach(function(e){et(t,function(e,t){ae(n,i,e,t)},r,e,true)})}}function Ke(e,t){if(e.type==="submit"||e.type==="click"){if(t.tagName==="FORM"){return true}if(h(t,'input[type="submit"], button')&&d(t,"form")!==null){return true}if(t.tagName==="A"&&t.href&&(t.getAttribute("href")==="#"||t.getAttribute("href").indexOf("#")!==0)){return true}}return false}function Ye(e,t){return Y(e).boosted&&e.tagName==="A"&&t.type==="click"&&(t.ctrlKey||t.metaKey)}function Qe(e,t){var r=e.eventFilter;if(r){try{return r(t)!==true}catch(e){ne(J().body,"htmx:eventFilter:error",{error:e,source:r.source});return true}}return false}function et(i,a,e,o,s){var l=Y(i);var t;if(o.from){t=_(i,o.from)}else{t=[i]}if(o.changed){l.lastValue=i.value}Q(t,function(r){var n=function(e){if(!ee(i)){r.removeEventListener(o.trigger,n);return}if(Ye(i,e)){return}if(s||Ke(e,i)){e.preventDefault()}if(Qe(o,e)){return}var t=Y(e);t.triggerSpec=o;if(t.handledFor==null){t.handledFor=[]}if(t.handledFor.indexOf(i)<0){t.handledFor.push(i);if(o.consume){e.stopPropagation()}if(o.target&&e.target){if(!h(e.target,o.target)){return}}if(o.once){if(l.triggeredOnce){return}else{l.triggeredOnce=true}}if(o.changed){if(l.lastValue===i.value){return}else{l.lastValue=i.value}}if(l.delayed){clearTimeout(l.delayed)}if(l.throttle){return}if(o.throttle){if(!l.throttle){a(i,e);l.throttle=setTimeout(function(){l.throttle=null},o.throttle)}}else if(o.delay){l.delayed=setTimeout(function(){a(i,e)},o.delay)}else{ie(i,"htmx:trigger");a(i,e)}}};if(e.listenerInfos==null){e.listenerInfos=[]}e.listenerInfos.push({trigger:o.trigger,listener:n,on:r});r.addEventListener(o.trigger,n)})}var tt=false;var rt=null;function nt(){if(!rt){rt=function(){tt=true};window.addEventListener("scroll",rt);setInterval(function(){if(tt){tt=false;Q(J().querySelectorAll("[hx-trigger='revealed'],[data-hx-trigger='revealed']"),function(e){it(e)})}},200)}}function it(t){if(!q(t,"data-hx-revealed")&&P(t)){t.setAttribute("data-hx-revealed","true");var e=Y(t);if(e.initHash){ie(t,"revealed")}else{t.addEventListener("htmx:afterProcessNode",function(e){ie(t,"revealed")},{once:true})}}}function at(e,t,r){var n=M(r);for(var i=0;i<n.length;i++){var a=n[i].split(/:(.+)/);if(a[0]==="connect"){ot(e,a[1],0)}if(a[0]==="send"){lt(e)}}}function ot(s,r,n){if(!ee(s)){return}if(r.indexOf("/")==0){var e=location.hostname+(location.port?":"+location.port:"");if(location.protocol=="https:"){r="wss://"+e+r}else if(location.protocol=="http:"){r="ws://"+e+r}}var t=z.createWebSocket(r);t.onerror=function(e){ne(s,"htmx:wsError",{error:e,socket:t});st(s)};t.onclose=function(e){if([1006,1012,1013].indexOf(e.code)>=0){var t=ut(n);setTimeout(function(){ot(s,r,n+1)},t)}};t.onopen=function(e){n=0};Y(s).webSocket=t;t.addEventListener("message",function(e){if(st(s)){return}var t=e.data;w(s,function(e){t=e.transformResponse(t,null,s)});var r=S(s);var n=l(t);var i=k(n.children);for(var a=0;a<i.length;a++){var o=i[a];me(G(o,"hx-swap-oob")||"true",o,r)}Bt(r.tasks)})}function st(e){if(!ee(e)){Y(e).webSocket.close();return true}}function lt(u){var f=c(u,function(e){return Y(e).webSocket!=null});if(f){u.addEventListener(ze(u)[0].trigger,function(e){var t=Y(f).webSocket;var r=Qt(u,f);var n=Jt(u,"post");var i=n.errors;var a=n.values;var o=fr(u);var s=te(a,o);var l=er(s,u);l["HEADERS"]=r;if(i&&i.length>0){ie(u,"htmx:validation:halted",i);return}t.send(JSON.stringify(l));if(Ke(e,u)){e.preventDefault()}})}else{ne(u,"htmx:noWebSocketSourceError")}}function ut(e){var t=z.config.wsReconnectDelay;if(typeof t==="function"){return t(e)}if(t==="full-jitter"){var r=Math.min(e,6);var n=1e3*Math.pow(2,r);return n*Math.random()}x('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"')}function ft(e,t,r){var n=M(r);for(var i=0;i<n.length;i++){var a=n[i].split(/:(.+)/);if(a[0]==="connect"){ct(e,a[1])}if(a[0]==="swap"){ht(e,a[1])}}}function ct(t,e){var r=z.createEventSource(e);r.onerror=function(e){ne(t,"htmx:sseError",{error:e,source:r});vt(t)};Y(t).sseEventSource=r}function ht(a,o){var s=c(a,gt);if(s){var l=Y(s).sseEventSource;var u=function(e){if(vt(s)){l.removeEventListener(o,u);return}var t=e.data;w(a,function(e){t=e.transformResponse(t,null,a)});var r=rr(a);var n=de(a);var i=S(a);Me(r.swapStyle,a,n,t,i);Bt(i.tasks);ie(a,"htmx:sseMessage",e)};Y(a).sseListener=u;l.addEventListener(o,u)}else{ne(a,"htmx:noSSESourceError")}}function dt(e,t,r){var n=c(e,gt);if(n){var i=Y(n).sseEventSource;var a=function(){if(!vt(n)){if(ee(e)){t(e)}else{i.removeEventListener(r,a)}}};Y(e).sseListener=a;i.addEventListener(r,a)}else{ne(e,"htmx:noSSESourceError")}}function vt(e){if(!ee(e)){Y(e).sseEventSource.close();return true}}function gt(e){return Y(e).sseEventSource!=null}function pt(e,t,r,n){var i=function(){if(!r.loaded){r.loaded=true;t(e)}};if(n){setTimeout(i,n)}else{i()}}function mt(t,i,e){var a=false;Q(R,function(r){if(q(t,"hx-"+r)){var n=G(t,"hx-"+r);a=true;i.path=n;i.verb=r;e.forEach(function(e){xt(t,e,i,function(e,t){ae(r,n,e,t)})})}});return a}function xt(n,e,t,r){if(e.sseEvent){dt(n,r,e.sseEvent)}else if(e.trigger==="revealed"){nt();et(n,r,t,e);it(n)}else if(e.trigger==="intersect"){var i={};if(e.root){i.root=re(n,e.root)}if(e.threshold){i.threshold=parseFloat(e.threshold)}var a=new IntersectionObserver(function(e){for(var t=0;t<e.length;t++){var r=e[t];if(r.isIntersecting){ie(n,"intersect");break}}},i);a.observe(n);et(n,r,t,e)}else if(e.trigger==="load"){if(!Qe(e,Lt("load",{elt:n}))){pt(n,r,t,e.delay)}}else if(e.pollInterval){t.polling=true;Ge(n,r,e)}else{et(n,r,t,e)}}function yt(e){if(e.type==="text/javascript"||e.type==="module"||e.type===""){var t=J().createElement("script");Q(e.attributes,function(e){t.setAttribute(e.name,e.value)});t.textContent=e.textContent;t.async=false;if(z.config.inlineScriptNonce){t.nonce=z.config.inlineScriptNonce}var r=e.parentElement;try{r.insertBefore(t,e)}catch(e){x(e)}finally{if(e.parentElement){e.parentElement.removeChild(e)}}}}function bt(e){if(h(e,"script")){yt(e)}Q(f(e,"script"),function(e){yt(e)})}function wt(){return document.querySelector("[hx-boost], [data-hx-boost]")}function St(e){if(e.querySelectorAll){var t=wt()?", a, form":"";var r=e.querySelectorAll(O+t+", [hx-sse], [data-hx-sse], [hx-ws],"+" [data-hx-ws], [hx-ext], [data-hx-ext], [hx-trigger], [data-hx-trigger], [hx-on], [data-hx-on]");return r}else{return[]}}function Et(n){var e=function(e){var t=d(e.target,"button, input[type='submit']");if(t!==null){var r=Y(n);r.lastButtonClicked=t}};n.addEventListener("click",e);n.addEventListener("focusin",e);n.addEventListener("focusout",function(e){var t=Y(n);t.lastButtonClicked=null})}function Ct(e){var t=Ue(e);var r=0;for(let e=0;e<t.length;e++){const n=t[e];if(n==="{"){r++}else if(n==="}"){r--}}return r}function Rt(t,e,r){var n=Y(t);n.onHandlers=[];var i=new Function("event",r+"; return;");var a=t.addEventListener(e,function(e){return i.call(t,e)});n.onHandlers.push({event:e,listener:a});return{nodeData:n,code:r,func:i,listener:a}}function Ot(e){var t=G(e,"hx-on");if(t){var r={};var n=t.split("\n");var i=null;var a=0;while(n.length>0){var o=n.shift();var s=o.match(/^\s*([a-zA-Z:\-]+:)(.*)/);if(a===0&&s){o.split(":");i=s[1].slice(0,-1);r[i]=s[2]}else{r[i]+=o}a+=Ct(o)}for(var l in r){Rt(e,l,r[l])}}}function qt(t){if(t.closest&&t.closest(z.config.disableSelector)){return}var r=Y(t);if(r.initHash!==Ce(t)){r.initHash=Ce(t);Re(t);Ot(t);ie(t,"htmx:beforeProcessNode");if(t.value){r.lastValue=t.value}var e=ze(t);var n=mt(t,r,e);if(!n){if(Z(t,"hx-boost")==="true"){Ze(t,r,e)}else if(q(t,"hx-trigger")){e.forEach(function(e){xt(t,e,r,function(){})})}}if(t.tagName==="FORM"){Et(t)}var i=G(t,"hx-sse");if(i){ft(t,r,i)}var a=G(t,"hx-ws");if(a){at(t,r,a)}ie(t,"htmx:afterProcessNode")}}function Tt(e){e=s(e);qt(e);Q(St(e),function(e){qt(e)})}function Ht(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}function Lt(e,t){var r;if(window.CustomEvent&&typeof window.CustomEvent==="function"){r=new CustomEvent(e,{bubbles:true,cancelable:true,detail:t})}else{r=J().createEvent("CustomEvent");r.initCustomEvent(e,true,true,t)}return r}function ne(e,t,r){ie(e,t,te({error:t},r))}function At(e){return e==="htmx:afterProcessNode"}function w(e,t){Q(wr(e),function(e){try{t(e)}catch(e){x(e)}})}function x(e){if(console.error){console.error(e)}else if(console.log){console.log("ERROR: ",e)}}function ie(e,t,r){e=s(e);if(r==null){r={}}r["elt"]=e;var n=Lt(t,r);if(z.logger&&!At(t)){z.logger(e,t,r)}if(r.error){x(r.error);ie(e,"htmx:error",{errorInfo:r})}var i=e.dispatchEvent(n);var a=Ht(t);if(i&&a!==t){var o=Lt(a,n.detail);i=i&&e.dispatchEvent(o)}w(e,function(e){i=i&&e.onEvent(t,n)!==false});return i}var Nt=location.pathname+location.search;function It(){var e=J().querySelector("[hx-history-elt],[data-hx-history-elt]");return e||J().body}function kt(e,t,r,n){if(!D()){return}e=X(e);var i=y(localStorage.getItem("htmx-history-cache"))||[];for(var a=0;a<i.length;a++){if(i[a].url===e){i.splice(a,1);break}}var o={url:e,content:t,title:r,scroll:n};ie(J().body,"htmx:historyItemCreated",{item:o,cache:i});i.push(o);while(i.length>z.config.historyCacheSize){i.shift()}while(i.length>0){try{localStorage.setItem("htmx-history-cache",JSON.stringify(i));break}catch(e){ne(J().body,"htmx:historyCacheError",{cause:e,cache:i});i.shift()}}}function Pt(e){if(!D()){return null}e=X(e);var t=y(localStorage.getItem("htmx-history-cache"))||[];for(var r=0;r<t.length;r++){if(t[r].url===e){return t[r]}}return null}function Mt(e){var t=z.config.requestClass;var r=e.cloneNode(true);Q(f(r,"."+t),function(e){n(e,t)});return r.innerHTML}function Dt(){var e=It();var t=Nt||location.pathname+location.search;var r=J().querySelector('[hx-history="false" i],[data-hx-history="false" i]');if(!r){ie(J().body,"htmx:beforeHistorySave",{path:t,historyElt:e});kt(t,Mt(e),J().title,window.scrollY)}if(z.config.historyEnabled)history.replaceState({htmx:true},J().title,window.location.href)}function Xt(e){if(z.config.getCacheBusterParam){e=e.replace(/org\.htmx\.cache-buster=[^&]*&?/,"");if(e.endsWith("&")||e.endsWith("?")){e=e.slice(0,-1)}}if(z.config.historyEnabled){history.pushState({htmx:true},"",e)}Nt=e}function Ft(e){if(z.config.historyEnabled)history.replaceState({htmx:true},"",e);Nt=e}function Bt(e){Q(e,function(e){e.call()})}function jt(a){var e=new XMLHttpRequest;var o={path:a,xhr:e};ie(J().body,"htmx:historyCacheMiss",o);e.open("GET",a,true);e.setRequestHeader("HX-History-Restore-Request","true");e.onload=function(){if(this.status>=200&&this.status<400){ie(J().body,"htmx:historyCacheMissLoad",o);var e=l(this.response);e=e.querySelector("[hx-history-elt],[data-hx-history-elt]")||e;var t=It();var r=S(t);var n=Pe(this.response);if(n){var i=b("title");if(i){i.innerHTML=n}else{window.document.title=n}}Ne(t,e,r);Bt(r.tasks);Nt=a;ie(J().body,"htmx:historyRestore",{path:a,cacheMiss:true,serverResponse:this.response})}else{ne(J().body,"htmx:historyCacheMissLoadError",o)}};e.send()}function Ut(e){Dt();e=e||location.pathname+location.search;var t=Pt(e);if(t){var r=l(t.content);var n=It();var i=S(n);Ne(n,r,i);Bt(i.tasks);document.title=t.title;window.scrollTo(0,t.scroll);Nt=e;ie(J().body,"htmx:historyRestore",{path:e,item:t})}else{if(z.config.refreshOnHistoryMiss){window.location.reload(true)}else{jt(e)}}}function Vt(e){var t=ce(e,"hx-indicator");if(t==null){t=[e]}Q(t,function(e){var t=Y(e);t.requestCount=(t.requestCount||0)+1;e.classList["add"].call(e.classList,z.config.requestClass)});return t}function _t(e){Q(e,function(e){var t=Y(e);t.requestCount=(t.requestCount||0)-1;if(t.requestCount===0){e.classList["remove"].call(e.classList,z.config.requestClass)}})}function Wt(e,t){for(var r=0;r<e.length;r++){var n=e[r];if(n.isSameNode(t)){return true}}return false}function zt(e){if(e.name===""||e.name==null||e.disabled){return false}if(e.type==="button"||e.type==="submit"||e.tagName==="image"||e.tagName==="reset"||e.tagName==="file"){return false}if(e.type==="checkbox"||e.type==="radio"){return e.checked}return true}function $t(t,r,n,e,i){if(e==null||Wt(t,e)){return}else{t.push(e)}if(zt(e)){var a=$(e,"name");var o=e.value;if(e.multiple){o=k(e.querySelectorAll("option:checked")).map(function(e){return e.value})}if(e.files){o=k(e.files)}if(a!=null&&o!=null){var s=r[a];if(s!==undefined){if(Array.isArray(s)){if(Array.isArray(o)){r[a]=s.concat(o)}else{s.push(o)}}else{if(Array.isArray(o)){r[a]=[s].concat(o)}else{r[a]=[s,o]}}}else{r[a]=o}}if(i){Gt(e,n)}}if(h(e,"form")){var l=e.elements;Q(l,function(e){$t(t,r,n,e,i)})}}function Gt(e,t){if(e.willValidate){ie(e,"htmx:validation:validate");if(!e.checkValidity()){t.push({elt:e,message:e.validationMessage,validity:e.validity});ie(e,"htmx:validation:failed",{message:e.validationMessage,validity:e.validity})}}}function Jt(e,t){var r=[];var n={};var i={};var a=[];var o=Y(e);var s=h(e,"form")&&e.noValidate!==true||G(e,"hx-validate")==="true";if(o.lastButtonClicked){s=s&&o.lastButtonClicked.formNoValidate!==true}if(t!=="get"){$t(r,i,a,d(e,"form"),s)}$t(r,n,a,e,s);if(o.lastButtonClicked){var l=$(o.lastButtonClicked,"name");if(l){n[l]=o.lastButtonClicked.value}}var u=ce(e,"hx-include");Q(u,function(e){$t(r,n,a,e,s);if(!h(e,"form")){Q(e.querySelectorAll(We),function(e){$t(r,n,a,e,s)})}});n=te(n,i);return{errors:a,values:n}}function Zt(e,t,r){if(e!==""){e+="&"}if(String(r)==="[object Object]"){r=JSON.stringify(r)}var n=encodeURIComponent(r);e+=encodeURIComponent(t)+"="+n;return e}function Kt(e){var t="";for(var r in e){if(e.hasOwnProperty(r)){var n=e[r];if(Array.isArray(n)){Q(n,function(e){t=Zt(t,r,e)})}else{t=Zt(t,r,n)}}}return t}function Yt(e){var t=new FormData;for(var r in e){if(e.hasOwnProperty(r)){var n=e[r];if(Array.isArray(n)){Q(n,function(e){t.append(r,e)})}else{t.append(r,n)}}}return t}function Qt(e,t,r){var n={"HX-Request":"true","HX-Trigger":$(e,"id"),"HX-Trigger-Name":$(e,"name"),"HX-Target":G(t,"id"),"HX-Current-URL":J().location.href};or(e,"hx-headers",false,n);if(r!==undefined){n["HX-Prompt"]=r}if(Y(e).boosted){n["HX-Boosted"]="true"}return n}function er(t,e){var r=Z(e,"hx-params");if(r){if(r==="none"){return{}}else if(r==="*"){return t}else if(r.indexOf("not ")===0){Q(r.substr(4).split(","),function(e){e=e.trim();delete t[e]});return t}else{var n={};Q(r.split(","),function(e){e=e.trim();n[e]=t[e]});return n}}else{return t}}function tr(e){return $(e,"href")&&$(e,"href").indexOf("#")>=0}function rr(e,t){var r=t?t:Z(e,"hx-swap");var n={swapStyle:Y(e).boosted?"innerHTML":z.config.defaultSwapStyle,swapDelay:z.config.defaultSwapDelay,settleDelay:z.config.defaultSettleDelay};if(Y(e).boosted&&!tr(e)){n["show"]="top"}if(r){var i=M(r);if(i.length>0){n["swapStyle"]=i[0];for(var a=1;a<i.length;a++){var o=i[a];if(o.indexOf("swap:")===0){n["swapDelay"]=v(o.substr(5))}if(o.indexOf("settle:")===0){n["settleDelay"]=v(o.substr(7))}if(o.indexOf("transition:")===0){n["transition"]=o.substr(11)==="true"}if(o.indexOf("scroll:")===0){var s=o.substr(7);var l=s.split(":");var u=l.pop();var f=l.length>0?l.join(":"):null;n["scroll"]=u;n["scrollTarget"]=f}if(o.indexOf("show:")===0){var c=o.substr(5);var l=c.split(":");var h=l.pop();var f=l.length>0?l.join(":"):null;n["show"]=h;n["showTarget"]=f}if(o.indexOf("focus-scroll:")===0){var d=o.substr("focus-scroll:".length);n["focusScroll"]=d=="true"}}}}return n}function nr(e){return Z(e,"hx-encoding")==="multipart/form-data"||h(e,"form")&&$(e,"enctype")==="multipart/form-data"}function ir(t,r,n){var i=null;w(r,function(e){if(i==null){i=e.encodeParameters(t,n,r)}});if(i!=null){return i}else{if(nr(r)){return Yt(n)}else{return Kt(n)}}}function S(e){return{tasks:[],elts:[e]}}function ar(e,t){var r=e[0];var n=e[e.length-1];if(t.scroll){var i=null;if(t.scrollTarget){i=re(r,t.scrollTarget)}if(t.scroll==="top"&&(r||i)){i=i||r;i.scrollTop=0}if(t.scroll==="bottom"&&(n||i)){i=i||n;i.scrollTop=i.scrollHeight}}if(t.show){var i=null;if(t.showTarget){var a=t.showTarget;if(t.showTarget==="window"){a="body"}i=re(r,a)}if(t.show==="top"&&(r||i)){i=i||r;i.scrollIntoView({block:"start",behavior:z.config.scrollBehavior})}if(t.show==="bottom"&&(n||i)){i=i||n;i.scrollIntoView({block:"end",behavior:z.config.scrollBehavior})}}}function or(e,t,r,n){if(n==null){n={}}if(e==null){return n}var i=G(e,t);if(i){var a=i.trim();var o=r;if(a==="unset"){return null}if(a.indexOf("javascript:")===0){a=a.substr(11);o=true}else if(a.indexOf("js:")===0){a=a.substr(3);o=true}if(a.indexOf("{")!==0){a="{"+a+"}"}var s;if(o){s=sr(e,function(){return Function("return ("+a+")")()},{})}else{s=y(a)}for(var l in s){if(s.hasOwnProperty(l)){if(n[l]==null){n[l]=s[l]}}}}return or(u(e),t,r,n)}function sr(e,t,r){if(z.config.allowEval){return t()}else{ne(e,"htmx:evalDisallowedError");return r}}function lr(e,t){return or(e,"hx-vars",true,t)}function ur(e,t){return or(e,"hx-vals",false,t)}function fr(e){return te(lr(e),ur(e))}function cr(t,r,n){if(n!==null){try{t.setRequestHeader(r,n)}catch(e){t.setRequestHeader(r,encodeURIComponent(n));t.setRequestHeader(r+"-URI-AutoEncoded","true")}}}function hr(t){if(t.responseURL&&typeof URL!=="undefined"){try{var e=new URL(t.responseURL);return e.pathname+e.search}catch(e){ne(J().body,"htmx:badResponseUrl",{url:t.responseURL})}}}function E(e,t){return e.getAllResponseHeaders().match(t)}function dr(e,t,r){e=e.toLowerCase();if(r){if(r instanceof Element||A(r,"String")){return ae(e,t,null,null,{targetOverride:s(r),returnPromise:true})}else{return ae(e,t,s(r.source),r.event,{handler:r.handler,headers:r.headers,values:r.values,targetOverride:s(r.target),swapOverride:r.swap,returnPromise:true})}}else{return ae(e,t,null,null,{returnPromise:true})}}function vr(e){var t=[];while(e){t.push(e);e=e.parentElement}return t}function ae(e,t,n,r,i,M){var a=null;var o=null;i=i!=null?i:{};if(i.returnPromise&&typeof Promise!=="undefined"){var s=new Promise(function(e,t){a=e;o=t})}if(n==null){n=J().body}var D=i.handler||pr;if(!ee(n)){return}var l=i.targetOverride||de(n);if(l==null||l==fe){ne(n,"htmx:targetError",{target:G(n,"hx-target")});return}if(!M){var X=function(){return ae(e,t,n,r,i,true)};var F={target:l,elt:n,path:t,verb:e,triggeringEvent:r,etc:i,issueRequest:X};if(ie(n,"htmx:confirm",F)===false){return}}var u=n;var f=Y(n);var c=Z(n,"hx-sync");var h=null;var d=false;if(c){var v=c.split(":");var g=v[0].trim();if(g==="this"){u=he(n,"hx-sync")}else{u=re(n,g)}c=(v[1]||"drop").trim();f=Y(u);if(c==="drop"&&f.xhr&&f.abortable!==true){return}else if(c==="abort"){if(f.xhr){return}else{d=true}}else if(c==="replace"){ie(u,"htmx:abort")}else if(c.indexOf("queue")===0){var B=c.split(" ");h=(B[1]||"last").trim()}}if(f.xhr){if(f.abortable){ie(u,"htmx:abort")}else{if(h==null){if(r){var p=Y(r);if(p&&p.triggerSpec&&p.triggerSpec.queue){h=p.triggerSpec.queue}}if(h==null){h="last"}}if(f.queuedRequests==null){f.queuedRequests=[]}if(h==="first"&&f.queuedRequests.length===0){f.queuedRequests.push(function(){ae(e,t,n,r,i)})}else if(h==="all"){f.queuedRequests.push(function(){ae(e,t,n,r,i)})}else if(h==="last"){f.queuedRequests=[];f.queuedRequests.push(function(){ae(e,t,n,r,i)})}return}}var m=new XMLHttpRequest;f.xhr=m;f.abortable=d;var x=function(){f.xhr=null;f.abortable=false;if(f.queuedRequests!=null&&f.queuedRequests.length>0){var e=f.queuedRequests.shift();e()}};var y=Z(n,"hx-prompt");if(y){var b=prompt(y);if(b===null||!ie(n,"htmx:prompt",{prompt:b,target:l})){K(a);x();return s}}var w=Z(n,"hx-confirm");if(w){if(!confirm(w)){K(a);x();return s}}var S=Qt(n,l,b);if(i.headers){S=te(S,i.headers)}var E=Jt(n,e);var C=E.errors;var R=E.values;if(i.values){R=te(R,i.values)}var j=fr(n);var O=te(R,j);var q=er(O,n);if(e!=="get"&&!nr(n)){S["Content-Type"]="application/x-www-form-urlencoded"}if(z.config.getCacheBusterParam&&e==="get"){q["org.htmx.cache-buster"]=$(l,"id")||"true"}if(t==null||t===""){t=J().location.href}var T=or(n,"hx-request");var H=Y(n).boosted;var L={boosted:H,parameters:q,unfilteredParameters:O,headers:S,target:l,verb:e,errors:C,withCredentials:i.credentials||T.credentials||z.config.withCredentials,timeout:i.timeout||T.timeout||z.config.timeout,path:t,triggeringEvent:r};if(!ie(n,"htmx:configRequest",L)){K(a);x();return s}t=L.path;e=L.verb;S=L.headers;q=L.parameters;C=L.errors;if(C&&C.length>0){ie(n,"htmx:validation:halted",L);K(a);x();return s}var U=t.split("#");var V=U[0];var A=U[1];var N=null;if(e==="get"){N=V;var _=Object.keys(q).length!==0;if(_){if(N.indexOf("?")<0){N+="?"}else{N+="&"}N+=Kt(q);if(A){N+="#"+A}}m.open("GET",N,true)}else{m.open(e.toUpperCase(),t,true)}m.overrideMimeType("text/html");m.withCredentials=L.withCredentials;m.timeout=L.timeout;if(T.noHeaders){}else{for(var I in S){if(S.hasOwnProperty(I)){var W=S[I];cr(m,I,W)}}}var k={xhr:m,target:l,requestConfig:L,etc:i,boosted:H,pathInfo:{requestPath:t,finalRequestPath:N||t,anchor:A}};m.onload=function(){try{var e=vr(n);k.pathInfo.responsePath=hr(m);D(n,k);_t(P);ie(n,"htmx:afterRequest",k);ie(n,"htmx:afterOnLoad",k);if(!ee(n)){var t=null;while(e.length>0&&t==null){var r=e.shift();if(ee(r)){t=r}}if(t){ie(t,"htmx:afterRequest",k);ie(t,"htmx:afterOnLoad",k)}}K(a);x()}catch(e){ne(n,"htmx:onLoadError",te({error:e},k));throw e}};m.onerror=function(){_t(P);ne(n,"htmx:afterRequest",k);ne(n,"htmx:sendError",k);K(o);x()};m.onabort=function(){_t(P);ne(n,"htmx:afterRequest",k);ne(n,"htmx:sendAbort",k);K(o);x()};m.ontimeout=function(){_t(P);ne(n,"htmx:afterRequest",k);ne(n,"htmx:timeout",k);K(o);x()};if(!ie(n,"htmx:beforeRequest",k)){K(a);x();return s}var P=Vt(n);Q(["loadstart","loadend","progress","abort"],function(t){Q([m,m.upload],function(e){e.addEventListener(t,function(e){ie(n,"htmx:xhr:"+t,{lengthComputable:e.lengthComputable,loaded:e.loaded,total:e.total})})})});ie(n,"htmx:beforeSend",k);m.send(e==="get"?null:ir(m,n,q));return s}function gr(e,t){var r=t.xhr;var n=null;var i=null;if(E(r,/HX-Push:/i)){n=r.getResponseHeader("HX-Push");i="push"}else if(E(r,/HX-Push-Url:/i)){n=r.getResponseHeader("HX-Push-Url");i="push"}else if(E(r,/HX-Replace-Url:/i)){n=r.getResponseHeader("HX-Replace-Url");i="replace"}if(n){if(n==="false"){return{}}else{return{type:i,path:n}}}var a=t.pathInfo.finalRequestPath;var o=t.pathInfo.responsePath;var s=Z(e,"hx-push-url");var l=Z(e,"hx-replace-url");var u=Y(e).boosted;var f=null;var c=null;if(s){f="push";c=s}else if(l){f="replace";c=l}else if(u){f="push";c=o||a}if(c){if(c==="false"){return{}}if(c==="true"){c=o||a}if(t.pathInfo.anchor&&c.indexOf("#")===-1){c=c+"#"+t.pathInfo.anchor}return{type:f,path:c}}else{return{}}}function pr(s,l){var u=l.xhr;var f=l.target;var e=l.etc;if(!ie(s,"htmx:beforeOnLoad",l))return;if(E(u,/HX-Trigger:/i)){De(u,"HX-Trigger",s)}if(E(u,/HX-Location:/i)){Dt();var t=u.getResponseHeader("HX-Location");var c;if(t.indexOf("{")===0){c=y(t);t=c["path"];delete c["path"]}dr("GET",t,c).then(function(){Xt(t)});return}if(E(u,/HX-Redirect:/i)){location.href=u.getResponseHeader("HX-Redirect");return}if(E(u,/HX-Refresh:/i)){if("true"===u.getResponseHeader("HX-Refresh")){location.reload();return}}if(E(u,/HX-Retarget:/i)){l.target=J().querySelector(u.getResponseHeader("HX-Retarget"))}var h=gr(s,l);var r=u.status>=200&&u.status<400&&u.status!==204;var d=u.response;var n=u.status>=400;var i=te({shouldSwap:r,serverResponse:d,isError:n},l);if(!ie(f,"htmx:beforeSwap",i))return;f=i.target;d=i.serverResponse;n=i.isError;l.target=f;l.failed=n;l.successful=!n;if(i.shouldSwap){if(u.status===286){$e(s)}w(s,function(e){d=e.transformResponse(d,u,s)});if(h.type){Dt()}var a=e.swapOverride;if(E(u,/HX-Reswap:/i)){a=u.getResponseHeader("HX-Reswap")}var c=rr(s,a);f.classList.add(z.config.swappingClass);var v=null;var g=null;var o=function(){try{var e=document.activeElement;var t={};try{t={elt:e,start:e?e.selectionStart:null,end:e?e.selectionEnd:null}}catch(e){}var n=S(f);Me(c.swapStyle,f,s,d,n);if(t.elt&&!ee(t.elt)&&t.elt.id){var r=document.getElementById(t.elt.id);var i={preventScroll:c.focusScroll!==undefined?!c.focusScroll:!z.config.defaultFocusScroll};if(r){if(t.start&&r.setSelectionRange){try{r.setSelectionRange(t.start,t.end)}catch(e){}}r.focus(i)}}f.classList.remove(z.config.swappingClass);Q(n.elts,function(e){if(e.classList){e.classList.add(z.config.settlingClass)}ie(e,"htmx:afterSwap",l)});if(E(u,/HX-Trigger-After-Swap:/i)){var a=s;if(!ee(s)){a=J().body}De(u,"HX-Trigger-After-Swap",a)}var o=function(){Q(n.tasks,function(e){e.call()});Q(n.elts,function(e){if(e.classList){e.classList.remove(z.config.settlingClass)}ie(e,"htmx:afterSettle",l)});if(h.type){if(h.type==="push"){Xt(h.path);ie(J().body,"htmx:pushedIntoHistory",{path:h.path})}else{Ft(h.path);ie(J().body,"htmx:replacedInHistory",{path:h.path})}}if(l.pathInfo.anchor){var e=b("#"+l.pathInfo.anchor);if(e){e.scrollIntoView({block:"start",behavior:"auto"})}}if(n.title){var t=b("title");if(t){t.innerHTML=n.title}else{window.document.title=n.title}}ar(n.elts,c);if(E(u,/HX-Trigger-After-Settle:/i)){var r=s;if(!ee(s)){r=J().body}De(u,"HX-Trigger-After-Settle",r)}K(v)};if(c.settleDelay>0){setTimeout(o,c.settleDelay)}else{o()}}catch(e){ne(s,"htmx:swapError",l);K(g);throw e}};var p=z.config.globalViewTransitions;if(c.hasOwnProperty("transition")){p=c.transition}if(p&&ie(s,"htmx:beforeTransition",l)&&typeof Promise!=="undefined"&&document.startViewTransition){var m=new Promise(function(e,t){v=e;g=t});var x=o;o=function(){document.startViewTransition(function(){x();return m})}}if(c.swapDelay>0){setTimeout(o,c.swapDelay)}else{o()}}if(n){ne(s,"htmx:responseError",te({error:"Response Status Error Code "+u.status+" from "+l.pathInfo.requestPath},l))}}var mr={};function xr(){return{init:function(e){return null},onEvent:function(e,t){return true},transformResponse:function(e,t,r){return e},isInlineSwap:function(e){return false},handleSwap:function(e,t,r,n){return false},encodeParameters:function(e,t,r){return null}}}function yr(e,t){if(t.init){t.init(C)}mr[e]=te(xr(),t)}function br(e){delete mr[e]}function wr(e,r,n){if(e==undefined){return r}if(r==undefined){r=[]}if(n==undefined){n=[]}var t=G(e,"hx-ext");if(t){Q(t.split(","),function(e){e=e.replace(/ /g,"");if(e.slice(0,7)=="ignore:"){n.push(e.slice(7));return}if(n.indexOf(e)<0){var t=mr[e];if(t&&r.indexOf(t)<0){r.push(t)}}})}return wr(u(e),r,n)}function Sr(e){if(J().readyState!=="loading"){e()}else{J().addEventListener("DOMContentLoaded",e)}}function Er(){if(z.config.includeIndicatorStyles!==false){J().head.insertAdjacentHTML("beforeend","<style>                      ."+z.config.indicatorClass+"{opacity:0;transition: opacity 200ms ease-in;}                      ."+z.config.requestClass+" ."+z.config.indicatorClass+"{opacity:1}                      ."+z.config.requestClass+"."+z.config.indicatorClass+"{opacity:1}                    </style>")}}function Cr(){var e=J().querySelector('meta[name="htmx-config"]');if(e){return y(e.content)}else{return null}}function Rr(){var e=Cr();if(e){z.config=te(z.config,e)}}Sr(function(){Rr();Er();var e=J().body;Tt(e);var t=J().querySelectorAll("[hx-trigger='restored'],[data-hx-trigger='restored']");e.addEventListener("htmx:abort",function(e){var t=e.target;var r=Y(t);if(r&&r.xhr){r.xhr.abort()}});var r=window.onpopstate;window.onpopstate=function(e){if(e.state&&e.state.htmx){Ut();Q(t,function(e){ie(e,"htmx:restored",{document:J(),triggerEvent:ie})})}else{if(r){r(e)}}};setTimeout(function(){ie(e,"htmx:load",{});e=null},0)});return z}()});
0 2
\ No newline at end of file
1 3
new file mode 100644
2 4
Binary files /dev/null and b/public/htmx.min.js.gz differ