htmx.org 1.9.5 → 1.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -1
- package/README.md +5 -9
- package/dist/ext/client-side-templates.js +62 -3
- package/dist/ext/disable-element.js +7 -5
- package/dist/ext/loading-states.js +48 -44
- package/dist/ext/morphdom-swap.js +2 -1
- package/dist/ext/response-targets.js +8 -0
- package/dist/ext/ws.js +1 -1
- package/dist/htmx.d.ts +78 -20
- package/dist/htmx.js +211 -94
- package/dist/htmx.min.js +1 -1
- package/dist/htmx.min.js.gz +0 -0
- package/package.json +7 -4
package/dist/htmx.js
CHANGED
|
@@ -74,7 +74,8 @@ return (function () {
|
|
|
74
74
|
getCacheBusterParam: false,
|
|
75
75
|
globalViewTransitions: false,
|
|
76
76
|
methodsThatUseUrlParams: ["get"],
|
|
77
|
-
selfRequestsOnly: false
|
|
77
|
+
selfRequestsOnly: false,
|
|
78
|
+
scrollIntoViewOnBoost: true
|
|
78
79
|
},
|
|
79
80
|
parseInterval:parseInterval,
|
|
80
81
|
_:internalEval,
|
|
@@ -86,7 +87,7 @@ return (function () {
|
|
|
86
87
|
sock.binaryType = htmx.config.wsBinaryType;
|
|
87
88
|
return sock;
|
|
88
89
|
},
|
|
89
|
-
version: "1.9.
|
|
90
|
+
version: "1.9.7"
|
|
90
91
|
};
|
|
91
92
|
|
|
92
93
|
/** @type {import("./htmx").HtmxInternalApi} */
|
|
@@ -306,6 +307,7 @@ return (function () {
|
|
|
306
307
|
case "th":
|
|
307
308
|
return parseHTML("<table><tbody><tr>" + resp + "</tr></tbody></table>", 3);
|
|
308
309
|
case "script":
|
|
310
|
+
case "style":
|
|
309
311
|
return parseHTML("<div>" + resp + "</div>", 1);
|
|
310
312
|
default:
|
|
311
313
|
return parseHTML(resp, 0);
|
|
@@ -573,9 +575,17 @@ return (function () {
|
|
|
573
575
|
}
|
|
574
576
|
}
|
|
575
577
|
|
|
578
|
+
function startsWith(str, prefix) {
|
|
579
|
+
return str.substring(0, prefix.length) === prefix
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function endsWith(str, suffix) {
|
|
583
|
+
return str.substring(str.length - suffix.length) === suffix
|
|
584
|
+
}
|
|
585
|
+
|
|
576
586
|
function normalizeSelector(selector) {
|
|
577
587
|
var trimmedSelector = selector.trim();
|
|
578
|
-
if (
|
|
588
|
+
if (startsWith(trimmedSelector, "<") && endsWith(trimmedSelector, "/>")) {
|
|
579
589
|
return trimmedSelector.substring(1, trimmedSelector.length - 2);
|
|
580
590
|
} else {
|
|
581
591
|
return trimmedSelector;
|
|
@@ -587,8 +597,12 @@ return (function () {
|
|
|
587
597
|
return [closest(elt, normalizeSelector(selector.substr(8)))];
|
|
588
598
|
} else if (selector.indexOf("find ") === 0) {
|
|
589
599
|
return [find(elt, normalizeSelector(selector.substr(5)))];
|
|
600
|
+
} else if (selector === "next") {
|
|
601
|
+
return [elt.nextElementSibling]
|
|
590
602
|
} else if (selector.indexOf("next ") === 0) {
|
|
591
603
|
return [scanForwardQuery(elt, normalizeSelector(selector.substr(5)))];
|
|
604
|
+
} else if (selector === "previous") {
|
|
605
|
+
return [elt.previousElementSibling]
|
|
592
606
|
} else if (selector.indexOf("previous ") === 0) {
|
|
593
607
|
return [scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)))];
|
|
594
608
|
} else if (selector === 'document') {
|
|
@@ -1270,12 +1284,14 @@ return (function () {
|
|
|
1270
1284
|
var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA);
|
|
1271
1285
|
if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") {
|
|
1272
1286
|
tokens.shift();
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1287
|
+
var selector = consumeUntil(
|
|
1288
|
+
tokens,
|
|
1289
|
+
WHITESPACE_OR_COMMA
|
|
1290
|
+
)
|
|
1291
|
+
// `next` and `previous` allow a selector-less syntax
|
|
1292
|
+
if (selector.length > 0) {
|
|
1293
|
+
from_arg += " " + selector;
|
|
1294
|
+
}
|
|
1279
1295
|
}
|
|
1280
1296
|
triggerSpec.from = from_arg;
|
|
1281
1297
|
} else if (token === "target" && tokens[0] === ":") {
|
|
@@ -1348,7 +1364,7 @@ return (function () {
|
|
|
1348
1364
|
var verb, path;
|
|
1349
1365
|
if (elt.tagName === "A") {
|
|
1350
1366
|
verb = "get";
|
|
1351
|
-
path = elt
|
|
1367
|
+
path = getRawAttribute(elt, 'href')
|
|
1352
1368
|
} else {
|
|
1353
1369
|
var rawAttribute = getRawAttribute(elt, "method");
|
|
1354
1370
|
verb = rawAttribute ? rawAttribute.toLowerCase() : "get";
|
|
@@ -1864,12 +1880,25 @@ return (function () {
|
|
|
1864
1880
|
}
|
|
1865
1881
|
|
|
1866
1882
|
function findHxOnWildcardElements(elt) {
|
|
1867
|
-
|
|
1883
|
+
var node = null
|
|
1884
|
+
var elements = []
|
|
1885
|
+
|
|
1886
|
+
if (document.evaluate) {
|
|
1887
|
+
var iter = document.evaluate('//*[@*[ starts-with(name(), "hx-on:") or starts-with(name(), "data-hx-on:") ]]', elt)
|
|
1888
|
+
while (node = iter.iterateNext()) elements.push(node)
|
|
1889
|
+
} else {
|
|
1890
|
+
var allElements = document.getElementsByTagName("*")
|
|
1891
|
+
for (var i = 0; i < allElements.length; i++) {
|
|
1892
|
+
var attributes = allElements[i].attributes
|
|
1893
|
+
for (var j = 0; j < attributes.length; j++) {
|
|
1894
|
+
var attrName = attributes[j].name
|
|
1895
|
+
if (startsWith(attrName, "hx-on:") || startsWith(attrName, "data-hx-on:")) {
|
|
1896
|
+
elements.push(allElements[i])
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1868
1901
|
|
|
1869
|
-
let node = null
|
|
1870
|
-
const elements = []
|
|
1871
|
-
const iter = document.evaluate('//*[@*[ starts-with(name(), "hx-on:") or starts-with(name(), "data-hx-on:") ]]', elt)
|
|
1872
|
-
while (node = iter.iterateNext()) elements.push(node)
|
|
1873
1902
|
return elements
|
|
1874
1903
|
}
|
|
1875
1904
|
|
|
@@ -1884,32 +1913,39 @@ return (function () {
|
|
|
1884
1913
|
}
|
|
1885
1914
|
}
|
|
1886
1915
|
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
var
|
|
1891
|
-
|
|
1892
|
-
|
|
1916
|
+
// Handle submit buttons/inputs that have the form attribute set
|
|
1917
|
+
// see https://developer.mozilla.org/docs/Web/HTML/Element/button
|
|
1918
|
+
function maybeSetLastButtonClicked(evt) {
|
|
1919
|
+
var elt = closest(evt.target, "button, input[type='submit']");
|
|
1920
|
+
var internalData = getRelatedFormData(evt)
|
|
1921
|
+
if (internalData) {
|
|
1922
|
+
internalData.lastButtonClicked = elt;
|
|
1893
1923
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1924
|
+
};
|
|
1925
|
+
function maybeUnsetLastButtonClicked(evt){
|
|
1926
|
+
var internalData = getRelatedFormData(evt)
|
|
1927
|
+
if (internalData) {
|
|
1928
|
+
internalData.lastButtonClicked = null;
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
function getRelatedFormData(evt) {
|
|
1932
|
+
var elt = closest(evt.target, "button, input[type='submit']");
|
|
1933
|
+
if (!elt) {
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1936
|
+
var form = resolveTarget('#' + getRawAttribute(elt, 'form')) || closest(elt, 'form');
|
|
1937
|
+
if (!form) {
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
return getInternalData(form);
|
|
1941
|
+
}
|
|
1942
|
+
function initButtonTracking(elt) {
|
|
1903
1943
|
// need to handle both click and focus in:
|
|
1904
1944
|
// focusin - in case someone tabs in to a button and hits the space bar
|
|
1905
1945
|
// click - on OSX buttons do not focus on click see https://bugs.webkit.org/show_bug.cgi?id=13724
|
|
1906
|
-
|
|
1907
1946
|
elt.addEventListener('click', maybeSetLastButtonClicked)
|
|
1908
1947
|
elt.addEventListener('focusin', maybeSetLastButtonClicked)
|
|
1909
|
-
elt.addEventListener('focusout',
|
|
1910
|
-
var internalData = getInternalData(form);
|
|
1911
|
-
internalData.lastButtonClicked = null;
|
|
1912
|
-
})
|
|
1948
|
+
elt.addEventListener('focusout', maybeUnsetLastButtonClicked)
|
|
1913
1949
|
}
|
|
1914
1950
|
|
|
1915
1951
|
function countCurlies(line) {
|
|
@@ -1928,7 +1964,9 @@ return (function () {
|
|
|
1928
1964
|
|
|
1929
1965
|
function addHxOnEventHandler(elt, eventName, code) {
|
|
1930
1966
|
var nodeData = getInternalData(elt);
|
|
1931
|
-
nodeData.onHandlers
|
|
1967
|
+
if (!Array.isArray(nodeData.onHandlers)) {
|
|
1968
|
+
nodeData.onHandlers = [];
|
|
1969
|
+
}
|
|
1932
1970
|
var func;
|
|
1933
1971
|
var listener = function (e) {
|
|
1934
1972
|
return maybeEval(elt, function() {
|
|
@@ -1951,7 +1989,7 @@ return (function () {
|
|
|
1951
1989
|
var curlyCount = 0;
|
|
1952
1990
|
while (lines.length > 0) {
|
|
1953
1991
|
var line = lines.shift();
|
|
1954
|
-
var match = line.match(/^\s*([a-zA-Z
|
|
1992
|
+
var match = line.match(/^\s*([a-zA-Z:\-\.]+:)(.*)/);
|
|
1955
1993
|
if (curlyCount === 0 && match) {
|
|
1956
1994
|
line.split(":")
|
|
1957
1995
|
currentEvent = match[1].slice(0, -1); // strip last colon
|
|
@@ -1975,10 +2013,10 @@ return (function () {
|
|
|
1975
2013
|
for (var i = 0; i < elt.attributes.length; i++) {
|
|
1976
2014
|
var name = elt.attributes[i].name
|
|
1977
2015
|
var value = elt.attributes[i].value
|
|
1978
|
-
if (
|
|
2016
|
+
if (startsWith(name, "hx-on:") || startsWith(name, "data-hx-on:")) {
|
|
1979
2017
|
let eventName = name.slice(name.indexOf(":") + 1)
|
|
1980
2018
|
// if the eventName starts with a colon, prepend "htmx" for shorthand support
|
|
1981
|
-
if (
|
|
2019
|
+
if (startsWith(eventName, ":")) eventName = "htmx" + eventName
|
|
1982
2020
|
|
|
1983
2021
|
addHxOnEventHandler(elt, eventName, value)
|
|
1984
2022
|
}
|
|
@@ -2127,7 +2165,7 @@ return (function () {
|
|
|
2127
2165
|
eventResult = eventResult && elt.dispatchEvent(kebabedEvent)
|
|
2128
2166
|
}
|
|
2129
2167
|
withExtensions(elt, function (extension) {
|
|
2130
|
-
eventResult = eventResult && (extension.onEvent(eventName, event) !== false)
|
|
2168
|
+
eventResult = eventResult && (extension.onEvent(eventName, event) !== false && !event.defaultPrevented)
|
|
2131
2169
|
});
|
|
2132
2170
|
return eventResult;
|
|
2133
2171
|
}
|
|
@@ -2147,6 +2185,12 @@ return (function () {
|
|
|
2147
2185
|
return;
|
|
2148
2186
|
}
|
|
2149
2187
|
|
|
2188
|
+
if (htmx.config.historyCacheSize <= 0) {
|
|
2189
|
+
// make sure that an eventually already existing cache is purged
|
|
2190
|
+
localStorage.removeItem("htmx-history-cache");
|
|
2191
|
+
return;
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2150
2194
|
url = normalizePath(url);
|
|
2151
2195
|
|
|
2152
2196
|
var historyCache = parseJSON(localStorage.getItem("htmx-history-cache")) || [];
|
|
@@ -2207,7 +2251,13 @@ return (function () {
|
|
|
2207
2251
|
// so we can prevent privileged data entering the cache.
|
|
2208
2252
|
// The page will still be reachable as a history entry, but htmx will fetch it
|
|
2209
2253
|
// live from the server onpopstate rather than look in the localStorage cache
|
|
2210
|
-
var disableHistoryCache
|
|
2254
|
+
var disableHistoryCache
|
|
2255
|
+
try {
|
|
2256
|
+
disableHistoryCache = getDocument().querySelector('[hx-history="false" i],[data-hx-history="false" i]')
|
|
2257
|
+
} catch (e) {
|
|
2258
|
+
// IE11: insensitive modifier not supported so fallback to case sensitive selector
|
|
2259
|
+
disableHistoryCache = getDocument().querySelector('[hx-history="false"],[data-hx-history="false"]')
|
|
2260
|
+
}
|
|
2211
2261
|
if (!disableHistoryCache) {
|
|
2212
2262
|
triggerEvent(getDocument().body, "htmx:beforeHistorySave", {path: path, historyElt: elt});
|
|
2213
2263
|
saveToHistoryCache(path, cleanInnerHtmlForHistory(elt), getDocument().title, window.scrollY);
|
|
@@ -2220,7 +2270,7 @@ return (function () {
|
|
|
2220
2270
|
// remove the cache buster parameter, if any
|
|
2221
2271
|
if (htmx.config.getCacheBusterParam) {
|
|
2222
2272
|
path = path.replace(/org\.htmx\.cache-buster=[^&]*&?/, '')
|
|
2223
|
-
if (
|
|
2273
|
+
if (endsWith(path, '&') || endsWith(path, "?")) {
|
|
2224
2274
|
path = path.slice(0, -1);
|
|
2225
2275
|
}
|
|
2226
2276
|
}
|
|
@@ -2316,7 +2366,20 @@ return (function () {
|
|
|
2316
2366
|
return indicators;
|
|
2317
2367
|
}
|
|
2318
2368
|
|
|
2319
|
-
function
|
|
2369
|
+
function disableElements(elt) {
|
|
2370
|
+
var disabledElts = findAttributeTargets(elt, 'hx-disabled-elt');
|
|
2371
|
+
if (disabledElts == null) {
|
|
2372
|
+
disabledElts = [];
|
|
2373
|
+
}
|
|
2374
|
+
forEach(disabledElts, function (disabledElement) {
|
|
2375
|
+
var internalData = getInternalData(disabledElement);
|
|
2376
|
+
internalData.requestCount = (internalData.requestCount || 0) + 1;
|
|
2377
|
+
disabledElement.setAttribute("disabled", "");
|
|
2378
|
+
});
|
|
2379
|
+
return disabledElts;
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
function removeRequestIndicators(indicators, disabled) {
|
|
2320
2383
|
forEach(indicators, function (ic) {
|
|
2321
2384
|
var internalData = getInternalData(ic);
|
|
2322
2385
|
internalData.requestCount = (internalData.requestCount || 0) - 1;
|
|
@@ -2324,6 +2387,13 @@ return (function () {
|
|
|
2324
2387
|
ic.classList["remove"].call(ic.classList, htmx.config.requestClass);
|
|
2325
2388
|
}
|
|
2326
2389
|
});
|
|
2390
|
+
forEach(disabled, function (disabledElement) {
|
|
2391
|
+
var internalData = getInternalData(disabledElement);
|
|
2392
|
+
internalData.requestCount = (internalData.requestCount || 0) - 1;
|
|
2393
|
+
if (internalData.requestCount === 0) {
|
|
2394
|
+
disabledElement.removeAttribute('disabled');
|
|
2395
|
+
}
|
|
2396
|
+
});
|
|
2327
2397
|
}
|
|
2328
2398
|
|
|
2329
2399
|
//====================================================================
|
|
@@ -2386,7 +2456,7 @@ return (function () {
|
|
|
2386
2456
|
if (shouldInclude(elt)) {
|
|
2387
2457
|
var name = getRawAttribute(elt,"name");
|
|
2388
2458
|
var value = elt.value;
|
|
2389
|
-
if (elt.multiple) {
|
|
2459
|
+
if (elt.multiple && elt.tagName === "SELECT") {
|
|
2390
2460
|
value = toArray(elt.querySelectorAll("option:checked")).map(function (e) { return e.value });
|
|
2391
2461
|
}
|
|
2392
2462
|
// include file inputs
|
|
@@ -2426,6 +2496,9 @@ return (function () {
|
|
|
2426
2496
|
var formValues = {};
|
|
2427
2497
|
var errors = [];
|
|
2428
2498
|
var internalData = getInternalData(elt);
|
|
2499
|
+
if (internalData.lastButtonClicked && !bodyContains(internalData.lastButtonClicked)) {
|
|
2500
|
+
internalData.lastButtonClicked = null
|
|
2501
|
+
}
|
|
2429
2502
|
|
|
2430
2503
|
// only validate when form is directly submitted and novalidate or formnovalidate are not set
|
|
2431
2504
|
// or if the element has an explicit hx-validate="true" on it
|
|
@@ -2593,43 +2666,43 @@ return (function () {
|
|
|
2593
2666
|
"swapDelay" : htmx.config.defaultSwapDelay,
|
|
2594
2667
|
"settleDelay" : htmx.config.defaultSettleDelay
|
|
2595
2668
|
}
|
|
2596
|
-
if (getInternalData(elt).boosted && !isAnchorLink(elt)) {
|
|
2669
|
+
if (htmx.config.scrollIntoViewOnBoost && getInternalData(elt).boosted && !isAnchorLink(elt)) {
|
|
2597
2670
|
swapSpec["show"] = "top"
|
|
2598
2671
|
}
|
|
2599
2672
|
if (swapInfo) {
|
|
2600
2673
|
var split = splitOnWhitespace(swapInfo);
|
|
2601
2674
|
if (split.length > 0) {
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
if (
|
|
2609
|
-
swapSpec["
|
|
2610
|
-
}
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
if (modifier.indexOf("scroll:") === 0) {
|
|
2615
|
-
var scrollSpec = modifier.substr(7);
|
|
2675
|
+
for (var i = 0; i < split.length; i++) {
|
|
2676
|
+
var value = split[i];
|
|
2677
|
+
if (value.indexOf("swap:") === 0) {
|
|
2678
|
+
swapSpec["swapDelay"] = parseInterval(value.substr(5));
|
|
2679
|
+
} else if (value.indexOf("settle:") === 0) {
|
|
2680
|
+
swapSpec["settleDelay"] = parseInterval(value.substr(7));
|
|
2681
|
+
} else if (value.indexOf("transition:") === 0) {
|
|
2682
|
+
swapSpec["transition"] = value.substr(11) === "true";
|
|
2683
|
+
} else if (value.indexOf("ignoreTitle:") === 0) {
|
|
2684
|
+
swapSpec["ignoreTitle"] = value.substr(12) === "true";
|
|
2685
|
+
} else if (value.indexOf("scroll:") === 0) {
|
|
2686
|
+
var scrollSpec = value.substr(7);
|
|
2616
2687
|
var splitSpec = scrollSpec.split(":");
|
|
2617
2688
|
var scrollVal = splitSpec.pop();
|
|
2618
2689
|
var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null;
|
|
2619
2690
|
swapSpec["scroll"] = scrollVal;
|
|
2620
2691
|
swapSpec["scrollTarget"] = selectorVal;
|
|
2621
|
-
}
|
|
2622
|
-
|
|
2623
|
-
var showSpec = modifier.substr(5);
|
|
2692
|
+
} else if (value.indexOf("show:") === 0) {
|
|
2693
|
+
var showSpec = value.substr(5);
|
|
2624
2694
|
var splitSpec = showSpec.split(":");
|
|
2625
2695
|
var showVal = splitSpec.pop();
|
|
2626
2696
|
var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null;
|
|
2627
2697
|
swapSpec["show"] = showVal;
|
|
2628
2698
|
swapSpec["showTarget"] = selectorVal;
|
|
2629
|
-
}
|
|
2630
|
-
|
|
2631
|
-
var focusScrollVal = modifier.substr("focus-scroll:".length);
|
|
2699
|
+
} else if (value.indexOf("focus-scroll:") === 0) {
|
|
2700
|
+
var focusScrollVal = value.substr("focus-scroll:".length);
|
|
2632
2701
|
swapSpec["focusScroll"] = focusScrollVal == "true";
|
|
2702
|
+
} else if (i == 0) {
|
|
2703
|
+
swapSpec["swapStyle"] = value;
|
|
2704
|
+
} else {
|
|
2705
|
+
logError('Unknown modifier in hx-swap: ' + value);
|
|
2633
2706
|
}
|
|
2634
2707
|
}
|
|
2635
2708
|
}
|
|
@@ -2853,9 +2926,18 @@ return (function () {
|
|
|
2853
2926
|
}
|
|
2854
2927
|
|
|
2855
2928
|
function verifyPath(elt, path, requestConfig) {
|
|
2856
|
-
var
|
|
2857
|
-
var
|
|
2858
|
-
|
|
2929
|
+
var sameHost
|
|
2930
|
+
var url
|
|
2931
|
+
if (typeof URL === "function") {
|
|
2932
|
+
url = new URL(path, document.location.href);
|
|
2933
|
+
var origin = document.location.origin;
|
|
2934
|
+
sameHost = origin === url.origin;
|
|
2935
|
+
} else {
|
|
2936
|
+
// IE11 doesn't support URL
|
|
2937
|
+
url = path
|
|
2938
|
+
sameHost = startsWith(path, document.location.origin)
|
|
2939
|
+
}
|
|
2940
|
+
|
|
2859
2941
|
if (htmx.config.selfRequestsOnly) {
|
|
2860
2942
|
if (!sameHost) {
|
|
2861
2943
|
return false;
|
|
@@ -2880,27 +2962,49 @@ return (function () {
|
|
|
2880
2962
|
var responseHandler = etc.handler || handleAjaxResponse;
|
|
2881
2963
|
|
|
2882
2964
|
if (!bodyContains(elt)) {
|
|
2883
|
-
|
|
2965
|
+
// do not issue requests for elements removed from the DOM
|
|
2966
|
+
maybeCall(resolve);
|
|
2967
|
+
return promise;
|
|
2884
2968
|
}
|
|
2885
2969
|
var target = etc.targetOverride || getTarget(elt);
|
|
2886
2970
|
if (target == null || target == DUMMY_ELT) {
|
|
2887
2971
|
triggerErrorEvent(elt, 'htmx:targetError', {target: getAttributeValue(elt, "hx-target")});
|
|
2888
|
-
|
|
2972
|
+
maybeCall(reject);
|
|
2973
|
+
return promise;
|
|
2889
2974
|
}
|
|
2890
2975
|
|
|
2976
|
+
var eltData = getInternalData(elt);
|
|
2977
|
+
var submitter = eltData.lastButtonClicked;
|
|
2978
|
+
|
|
2979
|
+
if (submitter) {
|
|
2980
|
+
var buttonPath = getRawAttribute(submitter, "formaction");
|
|
2981
|
+
if (buttonPath != null) {
|
|
2982
|
+
path = buttonPath;
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
var buttonVerb = getRawAttribute(submitter, "formmethod")
|
|
2986
|
+
if (buttonVerb != null) {
|
|
2987
|
+
// ignore buttons with formmethod="dialog"
|
|
2988
|
+
if (buttonVerb.toLowerCase() !== "dialog") {
|
|
2989
|
+
verb = buttonVerb;
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2994
|
+
var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm");
|
|
2891
2995
|
// allow event-based confirmation w/ a callback
|
|
2892
|
-
if (
|
|
2893
|
-
var issueRequest = function() {
|
|
2894
|
-
return issueAjaxRequest(verb, path, elt, event, etc,
|
|
2996
|
+
if (confirmed === undefined) {
|
|
2997
|
+
var issueRequest = function(skipConfirmation) {
|
|
2998
|
+
return issueAjaxRequest(verb, path, elt, event, etc, !!skipConfirmation);
|
|
2895
2999
|
}
|
|
2896
|
-
var confirmDetails = {target: target, elt: elt, path: path, verb: verb, triggeringEvent: event, etc: etc, issueRequest: issueRequest};
|
|
3000
|
+
var confirmDetails = {target: target, elt: elt, path: path, verb: verb, triggeringEvent: event, etc: etc, issueRequest: issueRequest, question: confirmQuestion};
|
|
2897
3001
|
if (triggerEvent(elt, 'htmx:confirm', confirmDetails) === false) {
|
|
2898
|
-
|
|
3002
|
+
maybeCall(resolve);
|
|
3003
|
+
return promise;
|
|
2899
3004
|
}
|
|
2900
3005
|
}
|
|
2901
3006
|
|
|
2902
3007
|
var syncElt = elt;
|
|
2903
|
-
var eltData = getInternalData(elt);
|
|
2904
3008
|
var syncStrategy = getClosestAttributeValue(elt, "hx-sync");
|
|
2905
3009
|
var queueStrategy = null;
|
|
2906
3010
|
var abortable = false;
|
|
@@ -2916,10 +3020,12 @@ return (function () {
|
|
|
2916
3020
|
syncStrategy = (syncStrings[1] || 'drop').trim();
|
|
2917
3021
|
eltData = getInternalData(syncElt);
|
|
2918
3022
|
if (syncStrategy === "drop" && eltData.xhr && eltData.abortable !== true) {
|
|
2919
|
-
|
|
3023
|
+
maybeCall(resolve);
|
|
3024
|
+
return promise;
|
|
2920
3025
|
} else if (syncStrategy === "abort") {
|
|
2921
3026
|
if (eltData.xhr) {
|
|
2922
|
-
|
|
3027
|
+
maybeCall(resolve);
|
|
3028
|
+
return promise;
|
|
2923
3029
|
} else {
|
|
2924
3030
|
abortable = true;
|
|
2925
3031
|
}
|
|
@@ -2963,7 +3069,8 @@ return (function () {
|
|
|
2963
3069
|
issueAjaxRequest(verb, path, elt, event, etc)
|
|
2964
3070
|
});
|
|
2965
3071
|
}
|
|
2966
|
-
|
|
3072
|
+
maybeCall(resolve);
|
|
3073
|
+
return promise;
|
|
2967
3074
|
}
|
|
2968
3075
|
}
|
|
2969
3076
|
|
|
@@ -2991,8 +3098,7 @@ return (function () {
|
|
|
2991
3098
|
}
|
|
2992
3099
|
}
|
|
2993
3100
|
|
|
2994
|
-
|
|
2995
|
-
if (confirmQuestion) {
|
|
3101
|
+
if (confirmQuestion && !confirmed) {
|
|
2996
3102
|
if(!confirm(confirmQuestion)) {
|
|
2997
3103
|
maybeCall(resolve);
|
|
2998
3104
|
endRequestLock()
|
|
@@ -3094,7 +3200,8 @@ return (function () {
|
|
|
3094
3200
|
|
|
3095
3201
|
if (!verifyPath(elt, finalPath, requestConfig)) {
|
|
3096
3202
|
triggerErrorEvent(elt, 'htmx:invalidPath', requestConfig)
|
|
3097
|
-
|
|
3203
|
+
maybeCall(reject);
|
|
3204
|
+
return promise;
|
|
3098
3205
|
};
|
|
3099
3206
|
|
|
3100
3207
|
xhr.open(verb.toUpperCase(), finalPath, true);
|
|
@@ -3128,7 +3235,7 @@ return (function () {
|
|
|
3128
3235
|
var hierarchy = hierarchyForElt(elt);
|
|
3129
3236
|
responseInfo.pathInfo.responsePath = getPathFromResponse(xhr);
|
|
3130
3237
|
responseHandler(elt, responseInfo);
|
|
3131
|
-
|
|
3238
|
+
removeRequestIndicators(indicators, disableElts);
|
|
3132
3239
|
triggerEvent(elt, 'htmx:afterRequest', responseInfo);
|
|
3133
3240
|
triggerEvent(elt, 'htmx:afterOnLoad', responseInfo);
|
|
3134
3241
|
// if the body no longer contains the element, trigger the event on the closest parent
|
|
@@ -3154,21 +3261,21 @@ return (function () {
|
|
|
3154
3261
|
}
|
|
3155
3262
|
}
|
|
3156
3263
|
xhr.onerror = function () {
|
|
3157
|
-
|
|
3264
|
+
removeRequestIndicators(indicators, disableElts);
|
|
3158
3265
|
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
|
|
3159
3266
|
triggerErrorEvent(elt, 'htmx:sendError', responseInfo);
|
|
3160
3267
|
maybeCall(reject);
|
|
3161
3268
|
endRequestLock();
|
|
3162
3269
|
}
|
|
3163
3270
|
xhr.onabort = function() {
|
|
3164
|
-
|
|
3271
|
+
removeRequestIndicators(indicators, disableElts);
|
|
3165
3272
|
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
|
|
3166
3273
|
triggerErrorEvent(elt, 'htmx:sendAbort', responseInfo);
|
|
3167
3274
|
maybeCall(reject);
|
|
3168
3275
|
endRequestLock();
|
|
3169
3276
|
}
|
|
3170
3277
|
xhr.ontimeout = function() {
|
|
3171
|
-
|
|
3278
|
+
removeRequestIndicators(indicators, disableElts);
|
|
3172
3279
|
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
|
|
3173
3280
|
triggerErrorEvent(elt, 'htmx:timeout', responseInfo);
|
|
3174
3281
|
maybeCall(reject);
|
|
@@ -3180,6 +3287,7 @@ return (function () {
|
|
|
3180
3287
|
return promise
|
|
3181
3288
|
}
|
|
3182
3289
|
var indicators = addRequestIndicatorClasses(elt);
|
|
3290
|
+
var disableElts = disableElements(elt);
|
|
3183
3291
|
|
|
3184
3292
|
forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) {
|
|
3185
3293
|
forEach([xhr, xhr.upload], function (target) {
|
|
@@ -3284,6 +3392,7 @@ return (function () {
|
|
|
3284
3392
|
var xhr = responseInfo.xhr;
|
|
3285
3393
|
var target = responseInfo.target;
|
|
3286
3394
|
var etc = responseInfo.etc;
|
|
3395
|
+
var requestConfig = responseInfo.requestConfig;
|
|
3287
3396
|
|
|
3288
3397
|
if (!triggerEvent(elt, 'htmx:beforeOnLoad', responseInfo)) return;
|
|
3289
3398
|
|
|
@@ -3307,16 +3416,17 @@ return (function () {
|
|
|
3307
3416
|
return;
|
|
3308
3417
|
}
|
|
3309
3418
|
|
|
3419
|
+
var shouldRefresh = hasHeader(xhr, /HX-Refresh:/i) && "true" === xhr.getResponseHeader("HX-Refresh");
|
|
3420
|
+
|
|
3310
3421
|
if (hasHeader(xhr, /HX-Redirect:/i)) {
|
|
3311
3422
|
location.href = xhr.getResponseHeader("HX-Redirect");
|
|
3423
|
+
shouldRefresh && location.reload();
|
|
3312
3424
|
return;
|
|
3313
3425
|
}
|
|
3314
3426
|
|
|
3315
|
-
if (
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
return;
|
|
3319
|
-
}
|
|
3427
|
+
if (shouldRefresh) {
|
|
3428
|
+
location.reload();
|
|
3429
|
+
return;
|
|
3320
3430
|
}
|
|
3321
3431
|
|
|
3322
3432
|
if (hasHeader(xhr,/HX-Retarget:/i)) {
|
|
@@ -3332,12 +3442,14 @@ return (function () {
|
|
|
3332
3442
|
var shouldSwap = xhr.status >= 200 && xhr.status < 400 && xhr.status !== 204;
|
|
3333
3443
|
var serverResponse = xhr.response;
|
|
3334
3444
|
var isError = xhr.status >= 400;
|
|
3335
|
-
var
|
|
3445
|
+
var ignoreTitle = htmx.config.ignoreTitle
|
|
3446
|
+
var beforeSwapDetails = mergeObjects({shouldSwap: shouldSwap, serverResponse:serverResponse, isError:isError, ignoreTitle:ignoreTitle }, responseInfo);
|
|
3336
3447
|
if (!triggerEvent(target, 'htmx:beforeSwap', beforeSwapDetails)) return;
|
|
3337
3448
|
|
|
3338
3449
|
target = beforeSwapDetails.target; // allow re-targeting
|
|
3339
3450
|
serverResponse = beforeSwapDetails.serverResponse; // allow updating content
|
|
3340
3451
|
isError = beforeSwapDetails.isError; // allow updating error
|
|
3452
|
+
ignoreTitle = beforeSwapDetails.ignoreTitle; // allow updating ignoring title
|
|
3341
3453
|
|
|
3342
3454
|
responseInfo.target = target; // Make updated target available to response events
|
|
3343
3455
|
responseInfo.failed = isError; // Make failed property available to response events
|
|
@@ -3363,6 +3475,10 @@ return (function () {
|
|
|
3363
3475
|
}
|
|
3364
3476
|
var swapSpec = getSwapSpecification(elt, swapOverride);
|
|
3365
3477
|
|
|
3478
|
+
if (swapSpec.hasOwnProperty('ignoreTitle')) {
|
|
3479
|
+
ignoreTitle = swapSpec.ignoreTitle;
|
|
3480
|
+
}
|
|
3481
|
+
|
|
3366
3482
|
target.classList.add(htmx.config.swappingClass);
|
|
3367
3483
|
|
|
3368
3484
|
// optional transition API promise callbacks
|
|
@@ -3441,6 +3557,7 @@ return (function () {
|
|
|
3441
3557
|
|
|
3442
3558
|
// if we need to save history, do so
|
|
3443
3559
|
if (historyUpdate.type) {
|
|
3560
|
+
triggerEvent(getDocument().body, 'htmx:beforeHistoryUpdate', mergeObjects({ history: historyUpdate }, responseInfo));
|
|
3444
3561
|
if (historyUpdate.type === "push") {
|
|
3445
3562
|
pushUrlIntoHistory(historyUpdate.path);
|
|
3446
3563
|
triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', {path: historyUpdate.path});
|
|
@@ -3450,13 +3567,13 @@ return (function () {
|
|
|
3450
3567
|
}
|
|
3451
3568
|
}
|
|
3452
3569
|
if (responseInfo.pathInfo.anchor) {
|
|
3453
|
-
var anchorTarget =
|
|
3570
|
+
var anchorTarget = getDocument().getElementById(responseInfo.pathInfo.anchor);
|
|
3454
3571
|
if(anchorTarget) {
|
|
3455
3572
|
anchorTarget.scrollIntoView({block:'start', behavior: "auto"});
|
|
3456
3573
|
}
|
|
3457
3574
|
}
|
|
3458
3575
|
|
|
3459
|
-
if(settleInfo.title) {
|
|
3576
|
+
if(settleInfo.title && !ignoreTitle) {
|
|
3460
3577
|
var titleElt = find("title");
|
|
3461
3578
|
if(titleElt) {
|
|
3462
3579
|
titleElt.innerHTML = settleInfo.title;
|