htmx.org 1.9.4 → 1.9.6
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 +26 -1
- package/README.md +3 -9
- package/dist/ext/client-side-templates.js +48 -1
- 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 +38 -26
- package/dist/ext/ws.js +1 -1
- package/dist/htmx.d.ts +78 -20
- package/dist/htmx.js +185 -59
- package/dist/htmx.js.gz +0 -0
- package/dist/htmx.min.js +1 -1
- package/dist/htmx.min.js.gz +0 -0
- package/package.json +3 -3
package/dist/htmx.js
CHANGED
|
@@ -60,6 +60,7 @@ return (function () {
|
|
|
60
60
|
settlingClass:'htmx-settling',
|
|
61
61
|
swappingClass:'htmx-swapping',
|
|
62
62
|
allowEval:true,
|
|
63
|
+
allowScriptTags:true,
|
|
63
64
|
inlineScriptNonce:'',
|
|
64
65
|
attributesToSettle:["class", "style", "width", "height"],
|
|
65
66
|
withCredentials:false,
|
|
@@ -73,6 +74,7 @@ return (function () {
|
|
|
73
74
|
getCacheBusterParam: false,
|
|
74
75
|
globalViewTransitions: false,
|
|
75
76
|
methodsThatUseUrlParams: ["get"],
|
|
77
|
+
selfRequestsOnly: false
|
|
76
78
|
},
|
|
77
79
|
parseInterval:parseInterval,
|
|
78
80
|
_:internalEval,
|
|
@@ -84,7 +86,7 @@ return (function () {
|
|
|
84
86
|
sock.binaryType = htmx.config.wsBinaryType;
|
|
85
87
|
return sock;
|
|
86
88
|
},
|
|
87
|
-
version: "1.9.
|
|
89
|
+
version: "1.9.6"
|
|
88
90
|
};
|
|
89
91
|
|
|
90
92
|
/** @type {import("./htmx").HtmxInternalApi} */
|
|
@@ -304,6 +306,7 @@ return (function () {
|
|
|
304
306
|
case "th":
|
|
305
307
|
return parseHTML("<table><tbody><tr>" + resp + "</tr></tbody></table>", 3);
|
|
306
308
|
case "script":
|
|
309
|
+
case "style":
|
|
307
310
|
return parseHTML("<div>" + resp + "</div>", 1);
|
|
308
311
|
default:
|
|
309
312
|
return parseHTML(resp, 0);
|
|
@@ -571,9 +574,17 @@ return (function () {
|
|
|
571
574
|
}
|
|
572
575
|
}
|
|
573
576
|
|
|
577
|
+
function startsWith(str, prefix) {
|
|
578
|
+
return str.substring(0, prefix.length) === prefix
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function endsWith(str, suffix) {
|
|
582
|
+
return str.substring(str.length - suffix.length) === suffix
|
|
583
|
+
}
|
|
584
|
+
|
|
574
585
|
function normalizeSelector(selector) {
|
|
575
586
|
var trimmedSelector = selector.trim();
|
|
576
|
-
if (
|
|
587
|
+
if (startsWith(trimmedSelector, "<") && endsWith(trimmedSelector, "/>")) {
|
|
577
588
|
return trimmedSelector.substring(1, trimmedSelector.length - 2);
|
|
578
589
|
} else {
|
|
579
590
|
return trimmedSelector;
|
|
@@ -593,6 +604,8 @@ return (function () {
|
|
|
593
604
|
return [document];
|
|
594
605
|
} else if (selector === 'window') {
|
|
595
606
|
return [window];
|
|
607
|
+
} else if (selector === 'body') {
|
|
608
|
+
return [document.body];
|
|
596
609
|
} else {
|
|
597
610
|
return getDocument().querySelectorAll(normalizeSelector(selector));
|
|
598
611
|
}
|
|
@@ -1344,7 +1357,7 @@ return (function () {
|
|
|
1344
1357
|
var verb, path;
|
|
1345
1358
|
if (elt.tagName === "A") {
|
|
1346
1359
|
verb = "get";
|
|
1347
|
-
path = elt
|
|
1360
|
+
path = getRawAttribute(elt, 'href')
|
|
1348
1361
|
} else {
|
|
1349
1362
|
var rawAttribute = getRawAttribute(elt, "method");
|
|
1350
1363
|
verb = rawAttribute ? rawAttribute.toLowerCase() : "get";
|
|
@@ -1821,7 +1834,7 @@ return (function () {
|
|
|
1821
1834
|
}
|
|
1822
1835
|
|
|
1823
1836
|
function evalScript(script) {
|
|
1824
|
-
if (script.type === "text/javascript" || script.type === "module" || script.type === "") {
|
|
1837
|
+
if (htmx.config.allowScriptTags && (script.type === "text/javascript" || script.type === "module" || script.type === "") ) {
|
|
1825
1838
|
var newScript = getDocument().createElement("script");
|
|
1826
1839
|
forEach(script.attributes, function (attr) {
|
|
1827
1840
|
newScript.setAttribute(attr.name, attr.value);
|
|
@@ -1860,12 +1873,25 @@ return (function () {
|
|
|
1860
1873
|
}
|
|
1861
1874
|
|
|
1862
1875
|
function findHxOnWildcardElements(elt) {
|
|
1863
|
-
|
|
1876
|
+
var node = null
|
|
1877
|
+
var elements = []
|
|
1878
|
+
|
|
1879
|
+
if (document.evaluate) {
|
|
1880
|
+
var iter = document.evaluate('//*[@*[ starts-with(name(), "hx-on:") or starts-with(name(), "data-hx-on:") ]]', elt)
|
|
1881
|
+
while (node = iter.iterateNext()) elements.push(node)
|
|
1882
|
+
} else {
|
|
1883
|
+
var allElements = document.getElementsByTagName("*")
|
|
1884
|
+
for (var i = 0; i < allElements.length; i++) {
|
|
1885
|
+
var attributes = allElements[i].attributes
|
|
1886
|
+
for (var j = 0; j < attributes.length; j++) {
|
|
1887
|
+
var attrName = attributes[j].name
|
|
1888
|
+
if (startsWith(attrName, "hx-on:") || startsWith(attrName, "data-hx-on:")) {
|
|
1889
|
+
elements.push(allElements[i])
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1864
1894
|
|
|
1865
|
-
let node = null
|
|
1866
|
-
const elements = []
|
|
1867
|
-
const iter = document.evaluate('//*[@*[ starts-with(name(), "hx-on:") or starts-with(name(), "data-hx-on:") ]]', elt)
|
|
1868
|
-
while (node = iter.iterateNext()) elements.push(node)
|
|
1869
1895
|
return elements
|
|
1870
1896
|
}
|
|
1871
1897
|
|
|
@@ -1925,25 +1951,29 @@ return (function () {
|
|
|
1925
1951
|
function addHxOnEventHandler(elt, eventName, code) {
|
|
1926
1952
|
var nodeData = getInternalData(elt);
|
|
1927
1953
|
nodeData.onHandlers = [];
|
|
1928
|
-
var func
|
|
1954
|
+
var func;
|
|
1929
1955
|
var listener = function (e) {
|
|
1930
|
-
return
|
|
1956
|
+
return maybeEval(elt, function() {
|
|
1957
|
+
if (!func) {
|
|
1958
|
+
func = new Function("event", code);
|
|
1959
|
+
}
|
|
1960
|
+
func.call(elt, e);
|
|
1961
|
+
});
|
|
1931
1962
|
};
|
|
1932
1963
|
elt.addEventListener(eventName, listener);
|
|
1933
1964
|
nodeData.onHandlers.push({event:eventName, listener:listener});
|
|
1934
|
-
return {nodeData:nodeData, code:code, func:func, listener:listener};
|
|
1935
1965
|
}
|
|
1936
1966
|
|
|
1937
1967
|
function processHxOn(elt) {
|
|
1938
1968
|
var hxOnValue = getAttributeValue(elt, 'hx-on');
|
|
1939
|
-
if (hxOnValue
|
|
1969
|
+
if (hxOnValue) {
|
|
1940
1970
|
var handlers = {}
|
|
1941
1971
|
var lines = hxOnValue.split("\n");
|
|
1942
1972
|
var currentEvent = null;
|
|
1943
1973
|
var curlyCount = 0;
|
|
1944
1974
|
while (lines.length > 0) {
|
|
1945
1975
|
var line = lines.shift();
|
|
1946
|
-
var match = line.match(/^\s*([a-zA-Z
|
|
1976
|
+
var match = line.match(/^\s*([a-zA-Z:\-\.]+:)(.*)/);
|
|
1947
1977
|
if (curlyCount === 0 && match) {
|
|
1948
1978
|
line.split(":")
|
|
1949
1979
|
currentEvent = match[1].slice(0, -1); // strip last colon
|
|
@@ -1967,10 +1997,10 @@ return (function () {
|
|
|
1967
1997
|
for (var i = 0; i < elt.attributes.length; i++) {
|
|
1968
1998
|
var name = elt.attributes[i].name
|
|
1969
1999
|
var value = elt.attributes[i].value
|
|
1970
|
-
if (
|
|
2000
|
+
if (startsWith(name, "hx-on:") || startsWith(name, "data-hx-on:")) {
|
|
1971
2001
|
let eventName = name.slice(name.indexOf(":") + 1)
|
|
1972
2002
|
// if the eventName starts with a colon, prepend "htmx" for shorthand support
|
|
1973
|
-
if (
|
|
2003
|
+
if (startsWith(eventName, ":")) eventName = "htmx" + eventName
|
|
1974
2004
|
|
|
1975
2005
|
addHxOnEventHandler(elt, eventName, value)
|
|
1976
2006
|
}
|
|
@@ -2119,7 +2149,7 @@ return (function () {
|
|
|
2119
2149
|
eventResult = eventResult && elt.dispatchEvent(kebabedEvent)
|
|
2120
2150
|
}
|
|
2121
2151
|
withExtensions(elt, function (extension) {
|
|
2122
|
-
eventResult = eventResult && (extension.onEvent(eventName, event) !== false)
|
|
2152
|
+
eventResult = eventResult && (extension.onEvent(eventName, event) !== false && !event.defaultPrevented)
|
|
2123
2153
|
});
|
|
2124
2154
|
return eventResult;
|
|
2125
2155
|
}
|
|
@@ -2199,7 +2229,13 @@ return (function () {
|
|
|
2199
2229
|
// so we can prevent privileged data entering the cache.
|
|
2200
2230
|
// The page will still be reachable as a history entry, but htmx will fetch it
|
|
2201
2231
|
// live from the server onpopstate rather than look in the localStorage cache
|
|
2202
|
-
var disableHistoryCache
|
|
2232
|
+
var disableHistoryCache
|
|
2233
|
+
try {
|
|
2234
|
+
disableHistoryCache = getDocument().querySelector('[hx-history="false" i],[data-hx-history="false" i]')
|
|
2235
|
+
} catch (e) {
|
|
2236
|
+
// IE11: insensitive modifier not supported so fallback to case sensitive selector
|
|
2237
|
+
disableHistoryCache = getDocument().querySelector('[hx-history="false"],[data-hx-history="false"]')
|
|
2238
|
+
}
|
|
2203
2239
|
if (!disableHistoryCache) {
|
|
2204
2240
|
triggerEvent(getDocument().body, "htmx:beforeHistorySave", {path: path, historyElt: elt});
|
|
2205
2241
|
saveToHistoryCache(path, cleanInnerHtmlForHistory(elt), getDocument().title, window.scrollY);
|
|
@@ -2212,7 +2248,7 @@ return (function () {
|
|
|
2212
2248
|
// remove the cache buster parameter, if any
|
|
2213
2249
|
if (htmx.config.getCacheBusterParam) {
|
|
2214
2250
|
path = path.replace(/org\.htmx\.cache-buster=[^&]*&?/, '')
|
|
2215
|
-
if (
|
|
2251
|
+
if (endsWith(path, '&') || endsWith(path, "?")) {
|
|
2216
2252
|
path = path.slice(0, -1);
|
|
2217
2253
|
}
|
|
2218
2254
|
}
|
|
@@ -2308,7 +2344,20 @@ return (function () {
|
|
|
2308
2344
|
return indicators;
|
|
2309
2345
|
}
|
|
2310
2346
|
|
|
2311
|
-
function
|
|
2347
|
+
function disableElements(elt) {
|
|
2348
|
+
var disabledElts = findAttributeTargets(elt, 'hx-disabled-elt');
|
|
2349
|
+
if (disabledElts == null) {
|
|
2350
|
+
disabledElts = [];
|
|
2351
|
+
}
|
|
2352
|
+
forEach(disabledElts, function (disabledElement) {
|
|
2353
|
+
var internalData = getInternalData(disabledElement);
|
|
2354
|
+
internalData.requestCount = (internalData.requestCount || 0) + 1;
|
|
2355
|
+
disabledElement.setAttribute("disabled", "");
|
|
2356
|
+
});
|
|
2357
|
+
return disabledElts;
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
function removeRequestIndicators(indicators, disabled) {
|
|
2312
2361
|
forEach(indicators, function (ic) {
|
|
2313
2362
|
var internalData = getInternalData(ic);
|
|
2314
2363
|
internalData.requestCount = (internalData.requestCount || 0) - 1;
|
|
@@ -2316,6 +2365,13 @@ return (function () {
|
|
|
2316
2365
|
ic.classList["remove"].call(ic.classList, htmx.config.requestClass);
|
|
2317
2366
|
}
|
|
2318
2367
|
});
|
|
2368
|
+
forEach(disabled, function (disabledElement) {
|
|
2369
|
+
var internalData = getInternalData(disabledElement);
|
|
2370
|
+
internalData.requestCount = (internalData.requestCount || 0) - 1;
|
|
2371
|
+
if (internalData.requestCount === 0) {
|
|
2372
|
+
disabledElement.removeAttribute('disabled');
|
|
2373
|
+
}
|
|
2374
|
+
});
|
|
2319
2375
|
}
|
|
2320
2376
|
|
|
2321
2377
|
//====================================================================
|
|
@@ -2591,37 +2647,37 @@ return (function () {
|
|
|
2591
2647
|
if (swapInfo) {
|
|
2592
2648
|
var split = splitOnWhitespace(swapInfo);
|
|
2593
2649
|
if (split.length > 0) {
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
if (
|
|
2601
|
-
swapSpec["
|
|
2602
|
-
}
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
if (modifier.indexOf("scroll:") === 0) {
|
|
2607
|
-
var scrollSpec = modifier.substr(7);
|
|
2650
|
+
for (var i = 0; i < split.length; i++) {
|
|
2651
|
+
var value = split[i];
|
|
2652
|
+
if (value.indexOf("swap:") === 0) {
|
|
2653
|
+
swapSpec["swapDelay"] = parseInterval(value.substr(5));
|
|
2654
|
+
} else if (value.indexOf("settle:") === 0) {
|
|
2655
|
+
swapSpec["settleDelay"] = parseInterval(value.substr(7));
|
|
2656
|
+
} else if (value.indexOf("transition:") === 0) {
|
|
2657
|
+
swapSpec["transition"] = value.substr(11) === "true";
|
|
2658
|
+
} else if (value.indexOf("ignoreTitle:") === 0) {
|
|
2659
|
+
swapSpec["ignoreTitle"] = value.substr(12) === "true";
|
|
2660
|
+
} else if (value.indexOf("scroll:") === 0) {
|
|
2661
|
+
var scrollSpec = value.substr(7);
|
|
2608
2662
|
var splitSpec = scrollSpec.split(":");
|
|
2609
2663
|
var scrollVal = splitSpec.pop();
|
|
2610
2664
|
var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null;
|
|
2611
2665
|
swapSpec["scroll"] = scrollVal;
|
|
2612
2666
|
swapSpec["scrollTarget"] = selectorVal;
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2615
|
-
var showSpec = modifier.substr(5);
|
|
2667
|
+
} else if (value.indexOf("show:") === 0) {
|
|
2668
|
+
var showSpec = value.substr(5);
|
|
2616
2669
|
var splitSpec = showSpec.split(":");
|
|
2617
2670
|
var showVal = splitSpec.pop();
|
|
2618
2671
|
var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null;
|
|
2619
2672
|
swapSpec["show"] = showVal;
|
|
2620
2673
|
swapSpec["showTarget"] = selectorVal;
|
|
2621
|
-
}
|
|
2622
|
-
|
|
2623
|
-
var focusScrollVal = modifier.substr("focus-scroll:".length);
|
|
2674
|
+
} else if (value.indexOf("focus-scroll:") === 0) {
|
|
2675
|
+
var focusScrollVal = value.substr("focus-scroll:".length);
|
|
2624
2676
|
swapSpec["focusScroll"] = focusScrollVal == "true";
|
|
2677
|
+
} else if (i == 0) {
|
|
2678
|
+
swapSpec["swapStyle"] = value;
|
|
2679
|
+
} else {
|
|
2680
|
+
logError('Unknown modifier in hx-swap: ' + value);
|
|
2625
2681
|
}
|
|
2626
2682
|
}
|
|
2627
2683
|
}
|
|
@@ -2844,6 +2900,27 @@ return (function () {
|
|
|
2844
2900
|
return arr;
|
|
2845
2901
|
}
|
|
2846
2902
|
|
|
2903
|
+
function verifyPath(elt, path, requestConfig) {
|
|
2904
|
+
var sameHost
|
|
2905
|
+
var url
|
|
2906
|
+
if (typeof URL === "function") {
|
|
2907
|
+
url = new URL(path, document.location.href);
|
|
2908
|
+
var origin = document.location.origin;
|
|
2909
|
+
sameHost = origin === url.origin;
|
|
2910
|
+
} else {
|
|
2911
|
+
// IE11 doesn't support URL
|
|
2912
|
+
url = path
|
|
2913
|
+
sameHost = startsWith(path, document.location.origin)
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
if (htmx.config.selfRequestsOnly) {
|
|
2917
|
+
if (!sameHost) {
|
|
2918
|
+
return false;
|
|
2919
|
+
}
|
|
2920
|
+
}
|
|
2921
|
+
return triggerEvent(elt, "htmx:validateUrl", mergeObjects({url: url, sameHost: sameHost}, requestConfig));
|
|
2922
|
+
}
|
|
2923
|
+
|
|
2847
2924
|
function issueAjaxRequest(verb, path, elt, event, etc, confirmed) {
|
|
2848
2925
|
var resolve = null;
|
|
2849
2926
|
var reject = null;
|
|
@@ -2860,12 +2937,30 @@ return (function () {
|
|
|
2860
2937
|
var responseHandler = etc.handler || handleAjaxResponse;
|
|
2861
2938
|
|
|
2862
2939
|
if (!bodyContains(elt)) {
|
|
2863
|
-
|
|
2940
|
+
// do not issue requests for elements removed from the DOM
|
|
2941
|
+
maybeCall(resolve);
|
|
2942
|
+
return promise;
|
|
2864
2943
|
}
|
|
2865
2944
|
var target = etc.targetOverride || getTarget(elt);
|
|
2866
2945
|
if (target == null || target == DUMMY_ELT) {
|
|
2867
2946
|
triggerErrorEvent(elt, 'htmx:targetError', {target: getAttributeValue(elt, "hx-target")});
|
|
2868
|
-
|
|
2947
|
+
maybeCall(reject);
|
|
2948
|
+
return promise;
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2951
|
+
var eltData = getInternalData(elt);
|
|
2952
|
+
var submitter = eltData.lastButtonClicked;
|
|
2953
|
+
|
|
2954
|
+
if (submitter) {
|
|
2955
|
+
var buttonPath = getRawAttribute(submitter, "formaction");
|
|
2956
|
+
if (buttonPath != null) {
|
|
2957
|
+
path = buttonPath;
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2960
|
+
var buttonVerb = getRawAttribute(submitter, "formmethod")
|
|
2961
|
+
if (buttonVerb != null) {
|
|
2962
|
+
verb = buttonVerb;
|
|
2963
|
+
}
|
|
2869
2964
|
}
|
|
2870
2965
|
|
|
2871
2966
|
// allow event-based confirmation w/ a callback
|
|
@@ -2875,12 +2970,12 @@ return (function () {
|
|
|
2875
2970
|
}
|
|
2876
2971
|
var confirmDetails = {target: target, elt: elt, path: path, verb: verb, triggeringEvent: event, etc: etc, issueRequest: issueRequest};
|
|
2877
2972
|
if (triggerEvent(elt, 'htmx:confirm', confirmDetails) === false) {
|
|
2878
|
-
|
|
2973
|
+
maybeCall(resolve);
|
|
2974
|
+
return promise;
|
|
2879
2975
|
}
|
|
2880
2976
|
}
|
|
2881
2977
|
|
|
2882
2978
|
var syncElt = elt;
|
|
2883
|
-
var eltData = getInternalData(elt);
|
|
2884
2979
|
var syncStrategy = getClosestAttributeValue(elt, "hx-sync");
|
|
2885
2980
|
var queueStrategy = null;
|
|
2886
2981
|
var abortable = false;
|
|
@@ -2896,10 +2991,12 @@ return (function () {
|
|
|
2896
2991
|
syncStrategy = (syncStrings[1] || 'drop').trim();
|
|
2897
2992
|
eltData = getInternalData(syncElt);
|
|
2898
2993
|
if (syncStrategy === "drop" && eltData.xhr && eltData.abortable !== true) {
|
|
2899
|
-
|
|
2994
|
+
maybeCall(resolve);
|
|
2995
|
+
return promise;
|
|
2900
2996
|
} else if (syncStrategy === "abort") {
|
|
2901
2997
|
if (eltData.xhr) {
|
|
2902
|
-
|
|
2998
|
+
maybeCall(resolve);
|
|
2999
|
+
return promise;
|
|
2903
3000
|
} else {
|
|
2904
3001
|
abortable = true;
|
|
2905
3002
|
}
|
|
@@ -2943,7 +3040,8 @@ return (function () {
|
|
|
2943
3040
|
issueAjaxRequest(verb, path, elt, event, etc)
|
|
2944
3041
|
});
|
|
2945
3042
|
}
|
|
2946
|
-
|
|
3043
|
+
maybeCall(resolve);
|
|
3044
|
+
return promise;
|
|
2947
3045
|
}
|
|
2948
3046
|
}
|
|
2949
3047
|
|
|
@@ -3072,6 +3170,12 @@ return (function () {
|
|
|
3072
3170
|
}
|
|
3073
3171
|
}
|
|
3074
3172
|
|
|
3173
|
+
if (!verifyPath(elt, finalPath, requestConfig)) {
|
|
3174
|
+
triggerErrorEvent(elt, 'htmx:invalidPath', requestConfig)
|
|
3175
|
+
maybeCall(reject);
|
|
3176
|
+
return promise;
|
|
3177
|
+
};
|
|
3178
|
+
|
|
3075
3179
|
xhr.open(verb.toUpperCase(), finalPath, true);
|
|
3076
3180
|
xhr.overrideMimeType("text/html");
|
|
3077
3181
|
xhr.withCredentials = requestConfig.withCredentials;
|
|
@@ -3103,7 +3207,7 @@ return (function () {
|
|
|
3103
3207
|
var hierarchy = hierarchyForElt(elt);
|
|
3104
3208
|
responseInfo.pathInfo.responsePath = getPathFromResponse(xhr);
|
|
3105
3209
|
responseHandler(elt, responseInfo);
|
|
3106
|
-
|
|
3210
|
+
removeRequestIndicators(indicators, disableElts);
|
|
3107
3211
|
triggerEvent(elt, 'htmx:afterRequest', responseInfo);
|
|
3108
3212
|
triggerEvent(elt, 'htmx:afterOnLoad', responseInfo);
|
|
3109
3213
|
// if the body no longer contains the element, trigger the event on the closest parent
|
|
@@ -3129,21 +3233,21 @@ return (function () {
|
|
|
3129
3233
|
}
|
|
3130
3234
|
}
|
|
3131
3235
|
xhr.onerror = function () {
|
|
3132
|
-
|
|
3236
|
+
removeRequestIndicators(indicators, disableElts);
|
|
3133
3237
|
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
|
|
3134
3238
|
triggerErrorEvent(elt, 'htmx:sendError', responseInfo);
|
|
3135
3239
|
maybeCall(reject);
|
|
3136
3240
|
endRequestLock();
|
|
3137
3241
|
}
|
|
3138
3242
|
xhr.onabort = function() {
|
|
3139
|
-
|
|
3243
|
+
removeRequestIndicators(indicators, disableElts);
|
|
3140
3244
|
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
|
|
3141
3245
|
triggerErrorEvent(elt, 'htmx:sendAbort', responseInfo);
|
|
3142
3246
|
maybeCall(reject);
|
|
3143
3247
|
endRequestLock();
|
|
3144
3248
|
}
|
|
3145
3249
|
xhr.ontimeout = function() {
|
|
3146
|
-
|
|
3250
|
+
removeRequestIndicators(indicators, disableElts);
|
|
3147
3251
|
triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo);
|
|
3148
3252
|
triggerErrorEvent(elt, 'htmx:timeout', responseInfo);
|
|
3149
3253
|
maybeCall(reject);
|
|
@@ -3155,6 +3259,7 @@ return (function () {
|
|
|
3155
3259
|
return promise
|
|
3156
3260
|
}
|
|
3157
3261
|
var indicators = addRequestIndicatorClasses(elt);
|
|
3262
|
+
var disableElts = disableElements(elt);
|
|
3158
3263
|
|
|
3159
3264
|
forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) {
|
|
3160
3265
|
forEach([xhr, xhr.upload], function (target) {
|
|
@@ -3259,6 +3364,7 @@ return (function () {
|
|
|
3259
3364
|
var xhr = responseInfo.xhr;
|
|
3260
3365
|
var target = responseInfo.target;
|
|
3261
3366
|
var etc = responseInfo.etc;
|
|
3367
|
+
var requestConfig = responseInfo.requestConfig;
|
|
3262
3368
|
|
|
3263
3369
|
if (!triggerEvent(elt, 'htmx:beforeOnLoad', responseInfo)) return;
|
|
3264
3370
|
|
|
@@ -3282,16 +3388,17 @@ return (function () {
|
|
|
3282
3388
|
return;
|
|
3283
3389
|
}
|
|
3284
3390
|
|
|
3391
|
+
var shouldRefresh = hasHeader(xhr, /HX-Refresh:/i) && "true" === xhr.getResponseHeader("HX-Refresh");
|
|
3392
|
+
|
|
3285
3393
|
if (hasHeader(xhr, /HX-Redirect:/i)) {
|
|
3286
3394
|
location.href = xhr.getResponseHeader("HX-Redirect");
|
|
3395
|
+
shouldRefresh && location.reload();
|
|
3287
3396
|
return;
|
|
3288
3397
|
}
|
|
3289
3398
|
|
|
3290
|
-
if (
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
return;
|
|
3294
|
-
}
|
|
3399
|
+
if (shouldRefresh) {
|
|
3400
|
+
location.reload();
|
|
3401
|
+
return;
|
|
3295
3402
|
}
|
|
3296
3403
|
|
|
3297
3404
|
if (hasHeader(xhr,/HX-Retarget:/i)) {
|
|
@@ -3307,12 +3414,14 @@ return (function () {
|
|
|
3307
3414
|
var shouldSwap = xhr.status >= 200 && xhr.status < 400 && xhr.status !== 204;
|
|
3308
3415
|
var serverResponse = xhr.response;
|
|
3309
3416
|
var isError = xhr.status >= 400;
|
|
3310
|
-
var
|
|
3417
|
+
var ignoreTitle = htmx.config.ignoreTitle
|
|
3418
|
+
var beforeSwapDetails = mergeObjects({shouldSwap: shouldSwap, serverResponse:serverResponse, isError:isError, ignoreTitle:ignoreTitle }, responseInfo);
|
|
3311
3419
|
if (!triggerEvent(target, 'htmx:beforeSwap', beforeSwapDetails)) return;
|
|
3312
3420
|
|
|
3313
3421
|
target = beforeSwapDetails.target; // allow re-targeting
|
|
3314
3422
|
serverResponse = beforeSwapDetails.serverResponse; // allow updating content
|
|
3315
3423
|
isError = beforeSwapDetails.isError; // allow updating error
|
|
3424
|
+
ignoreTitle = beforeSwapDetails.ignoreTitle; // allow updating ignoring title
|
|
3316
3425
|
|
|
3317
3426
|
responseInfo.target = target; // Make updated target available to response events
|
|
3318
3427
|
responseInfo.failed = isError; // Make failed property available to response events
|
|
@@ -3338,6 +3447,10 @@ return (function () {
|
|
|
3338
3447
|
}
|
|
3339
3448
|
var swapSpec = getSwapSpecification(elt, swapOverride);
|
|
3340
3449
|
|
|
3450
|
+
if (swapSpec.hasOwnProperty('ignoreTitle')) {
|
|
3451
|
+
ignoreTitle = swapSpec.ignoreTitle;
|
|
3452
|
+
}
|
|
3453
|
+
|
|
3341
3454
|
target.classList.add(htmx.config.swappingClass);
|
|
3342
3455
|
|
|
3343
3456
|
// optional transition API promise callbacks
|
|
@@ -3431,7 +3544,7 @@ return (function () {
|
|
|
3431
3544
|
}
|
|
3432
3545
|
}
|
|
3433
3546
|
|
|
3434
|
-
if(settleInfo.title) {
|
|
3547
|
+
if(settleInfo.title && !ignoreTitle) {
|
|
3435
3548
|
var titleElt = find("title");
|
|
3436
3549
|
if(titleElt) {
|
|
3437
3550
|
titleElt.innerHTML = settleInfo.title;
|
|
@@ -3582,9 +3695,22 @@ return (function () {
|
|
|
3582
3695
|
//====================================================================
|
|
3583
3696
|
// Initialization
|
|
3584
3697
|
//====================================================================
|
|
3698
|
+
var isReady = false
|
|
3699
|
+
getDocument().addEventListener('DOMContentLoaded', function() {
|
|
3700
|
+
isReady = true
|
|
3701
|
+
})
|
|
3585
3702
|
|
|
3703
|
+
/**
|
|
3704
|
+
* Execute a function now if DOMContentLoaded has fired, otherwise listen for it.
|
|
3705
|
+
*
|
|
3706
|
+
* This function uses isReady because there is no realiable way to ask the browswer whether
|
|
3707
|
+
* the DOMContentLoaded event has already been fired; there's a gap between DOMContentLoaded
|
|
3708
|
+
* firing and readystate=complete.
|
|
3709
|
+
*/
|
|
3586
3710
|
function ready(fn) {
|
|
3587
|
-
|
|
3711
|
+
// Checking readyState here is a failsafe in case the htmx script tag entered the DOM by
|
|
3712
|
+
// some means other than the initial page load.
|
|
3713
|
+
if (isReady || getDocument().readyState === 'complete') {
|
|
3588
3714
|
fn();
|
|
3589
3715
|
} else {
|
|
3590
3716
|
getDocument().addEventListener('DOMContentLoaded', fn);
|
package/dist/htmx.js.gz
ADDED
|
Binary file
|