diff options
Diffstat (limited to 'dist/htmx.js')
-rw-r--r-- | dist/htmx.js | 135 |
1 files changed, 86 insertions, 49 deletions
diff --git a/dist/htmx.js b/dist/htmx.js index 79a4702e..1f0709d7 100644 --- a/dist/htmx.js +++ b/dist/htmx.js @@ -75,6 +75,7 @@ return (function () { globalViewTransitions: false, methodsThatUseUrlParams: ["get"], selfRequestsOnly: false, + ignoreTitle: false, scrollIntoViewOnBoost: true }, parseInterval:parseInterval, @@ -87,7 +88,7 @@ return (function () { sock.binaryType = htmx.config.wsBinaryType; return sock; }, - version: "1.9.8" + version: "1.9.9" }; /** @type {import("./htmx").HtmxInternalApi} */ @@ -1145,6 +1146,8 @@ return (function () { var SYMBOL_CONT = /[_$a-zA-Z0-9]/; var STRINGISH_START = ['"', "'", "/"]; var NOT_WHITESPACE = /[^\s]/; + var COMBINED_SELECTOR_START = /[{(]/; + var COMBINED_SELECTOR_END = /[})]/; function tokenizeString(str) { var tokens = []; var position = 0; @@ -1233,6 +1236,18 @@ return (function () { return result; } + function consumeCSSSelector(tokens) { + var result; + if (tokens.length > 0 && COMBINED_SELECTOR_START.test(tokens[0])) { + tokens.shift(); + result = consumeUntil(tokens, COMBINED_SELECTOR_END).trim(); + tokens.shift(); + } else { + result = consumeUntil(tokens, WHITESPACE_OR_COMMA); + } + return result; + } + var INPUT_SELECTOR = 'input, textarea, select'; /** @@ -1281,29 +1296,33 @@ return (function () { triggerSpec.delay = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA)); } else if (token === "from" && tokens[0] === ":") { tokens.shift(); - var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA); - if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") { - tokens.shift(); - var selector = consumeUntil( - tokens, - WHITESPACE_OR_COMMA - ) - // `next` and `previous` allow a selector-less syntax - if (selector.length > 0) { - from_arg += " " + selector; + if (COMBINED_SELECTOR_START.test(tokens[0])) { + var from_arg = consumeCSSSelector(tokens); + } else { + var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA); + if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") { + tokens.shift(); + var selector = consumeCSSSelector(tokens); + // `next` and `previous` allow a selector-less syntax + if (selector.length > 0) { + from_arg += " " + selector; + } } } triggerSpec.from = from_arg; } else if (token === "target" && tokens[0] === ":") { tokens.shift(); - triggerSpec.target = consumeUntil(tokens, WHITESPACE_OR_COMMA); + triggerSpec.target = consumeCSSSelector(tokens); } else if (token === "throttle" && tokens[0] === ":") { tokens.shift(); triggerSpec.throttle = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA)); } else if (token === "queue" && tokens[0] === ":") { tokens.shift(); triggerSpec.queue = consumeUntil(tokens, WHITESPACE_OR_COMMA); - } else if ((token === "root" || token === "threshold") && tokens[0] === ":") { + } else if (token === "root" && tokens[0] === ":") { + tokens.shift(); + triggerSpec[token] = consumeCSSSelector(tokens); + } else if (token === "threshold" && tokens[0] === ":") { tokens.shift(); triggerSpec[token] = consumeUntil(tokens, WHITESPACE_OR_COMMA); } else { @@ -2906,6 +2925,7 @@ return (function () { values : context.values, targetOverride: resolveTarget(context.target), swapOverride: context.swap, + select: context.select, returnPromise: true }); } @@ -2960,6 +2980,7 @@ return (function () { elt = getDocument().body; } var responseHandler = etc.handler || handleAjaxResponse; + var select = etc.select || null; if (!bodyContains(elt)) { // do not issue requests for elements removed from the DOM @@ -3108,6 +3129,11 @@ return (function () { var headers = getHeaders(elt, target, promptResponse); + + if (verb !== 'get' && !usesFormData(elt)) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + if (etc.headers) { headers = mergeObjects(headers, etc.headers); } @@ -3121,10 +3147,6 @@ return (function () { var allParameters = mergeObjects(rawParameters, expressionVars); var filteredParameters = filterValues(allParameters, elt); - if (verb !== 'get' && !usesFormData(elt)) { - headers['Content-Type'] = 'application/x-www-form-urlencoded'; - } - if (htmx.config.getCacheBusterParam && verb === 'get') { filteredParameters['org.htmx.cache-buster'] = getRawAttribute(target, "id") || "true"; } @@ -3222,7 +3244,7 @@ return (function () { } var responseInfo = { - xhr: xhr, target: target, requestConfig: requestConfig, etc: etc, boosted: eltIsBoosted, + xhr: xhr, target: target, requestConfig: requestConfig, etc: etc, boosted: eltIsBoosted, select: select, pathInfo: { requestPath: path, finalRequestPath: finalPath, @@ -3393,6 +3415,7 @@ return (function () { var target = responseInfo.target; var etc = responseInfo.etc; var requestConfig = responseInfo.requestConfig; + var select = responseInfo.select; if (!triggerEvent(elt, 'htmx:beforeOnLoad', responseInfo)) return; @@ -3502,10 +3525,26 @@ return (function () { } var selectOverride; + if (select) { + selectOverride = select; + } + if (hasHeader(xhr, /HX-Reselect:/i)) { selectOverride = xhr.getResponseHeader("HX-Reselect"); } + // if we need to save history, do so, before swapping so that relative resources have the correct base URL + if (historyUpdate.type) { + triggerEvent(getDocument().body, 'htmx:beforeHistoryUpdate', mergeObjects({ history: historyUpdate }, responseInfo)); + if (historyUpdate.type === "push") { + pushUrlIntoHistory(historyUpdate.path); + triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', {path: historyUpdate.path}); + } else { + replaceUrlInHistory(historyUpdate.path); + triggerEvent(getDocument().body, 'htmx:replacedInHistory', {path: historyUpdate.path}); + } + } + var settleInfo = makeSettleInfo(target); selectAndSwap(swapSpec.swapStyle, target, elt, serverResponse, settleInfo, selectOverride); @@ -3555,17 +3594,6 @@ return (function () { triggerEvent(elt, 'htmx:afterSettle', responseInfo); }); - // if we need to save history, do so - if (historyUpdate.type) { - triggerEvent(getDocument().body, 'htmx:beforeHistoryUpdate', mergeObjects({ history: historyUpdate }, responseInfo)); - if (historyUpdate.type === "push") { - pushUrlIntoHistory(historyUpdate.path); - triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', {path: historyUpdate.path}); - } else { - replaceUrlInHistory(historyUpdate.path); - triggerEvent(getDocument().body, 'htmx:replacedInHistory', {path: historyUpdate.path}); - } - } if (responseInfo.pathInfo.anchor) { var anchorTarget = getDocument().getElementById(responseInfo.pathInfo.anchor); if(anchorTarget) { @@ -3724,25 +3752,34 @@ return (function () { //==================================================================== // Initialization //==================================================================== - var isReady = false - getDocument().addEventListener('DOMContentLoaded', function() { - isReady = true - }) - /** - * Execute a function now if DOMContentLoaded has fired, otherwise listen for it. - * - * This function uses isReady because there is no realiable way to ask the browswer whether - * the DOMContentLoaded event has already been fired; there's a gap between DOMContentLoaded - * firing and readystate=complete. + * We want to initialize the page elements after DOMContentLoaded + * fires, but there isn't always a good way to tell whether + * it has already fired when we get here or not. */ - function ready(fn) { - // Checking readyState here is a failsafe in case the htmx script tag entered the DOM by - // some means other than the initial page load. - if (isReady || getDocument().readyState === 'complete') { - fn(); - } else { - getDocument().addEventListener('DOMContentLoaded', fn); + function ready(functionToCall) { + // call the function exactly once no matter how many times this is called + var callReadyFunction = function() { + if (!functionToCall) return; + functionToCall(); + functionToCall = null; + }; + + if (getDocument().readyState === "complete") { + // DOMContentLoaded definitely fired, we can initialize the page + callReadyFunction(); + } + else { + /* DOMContentLoaded *maybe* already fired, wait for + * the next DOMContentLoaded or readystatechange event + */ + getDocument().addEventListener("DOMContentLoaded", function() { + callReadyFunction(); + }); + getDocument().addEventListener("readystatechange", function() { + if (getDocument().readyState !== "complete") return; + callReadyFunction(); + }); } } @@ -3750,9 +3787,9 @@ return (function () { if (htmx.config.includeIndicatorStyles !== false) { getDocument().head.insertAdjacentHTML("beforeend", "<style>\ - ." + htmx.config.indicatorClass + "{opacity:0;transition: opacity 200ms ease-in;}\ - ." + htmx.config.requestClass + " ." + htmx.config.indicatorClass + "{opacity:1}\ - ." + htmx.config.requestClass + "." + htmx.config.indicatorClass + "{opacity:1}\ + ." + htmx.config.indicatorClass + "{opacity:0}\ + ." + htmx.config.requestClass + " ." + htmx.config.indicatorClass + "{opacity:1; transition: opacity 200ms ease-in;}\ + ." + htmx.config.requestClass + "." + htmx.config.indicatorClass + "{opacity:1; transition: opacity 200ms ease-in;}\ </style>"); } } |