// @ts-nocheck /** * @copyright Big Sky Software 2024 * @copyright Big Sky Software 2024 * @license 0BSD * @link https://github.com/bigskysoftware/htmx/blob/master/dist/htmx.esm.js * @author Big Sky Software * * This source code is copied from HTMX's GitHub repository, located at * https://github.com/bigskysoftware/htmx/blob/master/dist/htmx.esm.js. * * This source code and the original are licensed under the Zero-Clause BSD license, * which a copy is available in the original [GitHub](https://github.com/bigskysoftware/htmx/blob/master/LICENSE) * and here below: * * Zero-Clause BSD * ============= * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted. * * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @author Big Sky Software */ /* eslint-disable */ var htmx = (function () { 'use strict'; // Public API const htmx = { /** @type {typeof internalEval} */ _: null, /** @type {typeof addClassToElement} */ addClass: null, /** @type {typeof ajaxHelper} */ ajax: null, /** @type {typeof closest} */ closest: null, /** * A property holding the configuration htmx uses at runtime. * * Note that using a [meta tag](https://htmx.org/docs/#config) is the preferred mechanism for setting these properties. * @see https://htmx.org/api/#config */ config: { /** * The class to temporarily place on elements that htmx has added to the DOM. * @type string * @default 'htmx-added' */ addedClass: 'htmx-added', /** * 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. * @type boolean * @default true */ allowEval: true, /** * Whether to process OOB swaps on elements that are nested within the main response element. * @type boolean * @default true */ allowNestedOobSwaps: true, /** * If set to false, disables the interpretation of script tags. * @type boolean * @default true */ allowScriptTags: true, /** * The attributes to settle during the settling phase. * @type string[] * @default ['class', 'style', 'width', 'height'] */ attributesToSettle: ['class', 'style', 'width', 'height'], /** * If the focused element should be scrolled into view. * @type boolean * @default false */ defaultFocusScroll: false, /** * The default delay between completing the content swap and settling attributes. * @type number * @default 20 */ defaultSettleDelay: 20, /** * The default delay between receiving a response from the server and doing the swap. * @type number * @default 0 */ defaultSwapDelay: 0, /** * The default swap style to use if **[hx-swap](https://htmx.org/attributes/hx-swap)** is omitted. * @type HtmxSwapStyle * @default 'innerHTML' */ defaultSwapStyle: 'innerHTML', /** @type boolean */ disableInheritance: false, /** * @type string * @default '[hx-disable], [data-hx-disable]' */ disableSelector: '[hx-disable], [data-hx-disable]', /** * If set to true htmx will include a cache-busting parameter in GET requests to avoid caching partial responses by the browser. * @type boolean * @default false */ getCacheBusterParam: false, /** * If set to true, htmx will use the View Transition API when swapping in new content. * @type boolean * @default false */ globalViewTransitions: false, /** * The number of pages to keep in **localStorage** for history support. * @type number * @default 10 */ historyCacheSize: 10, /** * Whether to use history. * @type boolean * @default true */ historyEnabled: true, /** * If set to true htmx will not update the title of the document when a title tag is found in new content. * @type boolean * @default false */ ignoreTitle: false, /** * If true, htmx will inject a small amount of CSS into the page to make indicators invisible unless the **htmx-indicator** class is present. * @type boolean * @default true */ includeIndicatorStyles: true, /** * The class to place on indicators when a request is in flight. * @type string * @default 'htmx-indicator' */ indicatorClass: 'htmx-indicator', /** * If set, the nonce will be added to inline scripts. * @type string * @default '' */ inlineScriptNonce: '', /** * If set, the nonce will be added to inline styles. * @type string * @default '' */ inlineStyleNonce: '', /** * Htmx will format requests with these methods by encoding their parameters in the URL, not the request body. * @type {(HttpVerb)[]} * @default ['get', 'delete'] */ methodsThatUseUrlParams: ['get', 'delete'], /** * @type boolean * @default false */ refreshOnHistoryMiss: false, /** * The class to place on triggering elements when a request is in flight. * @type string * @default 'htmx-request' */ requestClass: 'htmx-request', /** @type HtmxResponseHandlingConfig[] */ responseHandling: [ { code: '204', swap: false }, { code: '[23]..', swap: true }, { code: '[45]..', error: true, swap: false }, ], /** * @type {'auto' | 'instant' | 'smooth'} * @default 'instant' */ scrollBehavior: 'instant', /** * Whether the target of a boosted element is scrolled into the viewport. * @type boolean * @default true */ scrollIntoViewOnBoost: true, /** * If set to true, disables htmx-based requests to non-origin hosts. * @type boolean * @default false */ selfRequestsOnly: true, /** * The class to place on target elements when htmx is in the settling phase. * @type string * @default 'htmx-settling' */ settlingClass: 'htmx-settling', /** * The class to place on target elements when htmx is in the swapping phase. * @type string * @default 'htmx-swapping' */ swappingClass: 'htmx-swapping', /** * @type number * @default 0 */ timeout: 0, /** * The cache to store evaluated trigger specifications into. * You may define a simple object to use a never-clearing cache, or implement your own system using a [proxy object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy). * @type {object | null} * @default null */ triggerSpecsCache: null, /** * Allow cross-site Access-Control requests using credentials such as cookies, authorization headers or TLS client certificates. * @type boolean * @default false */ withCredentials: false, /** * The type of binary data being received over the WebSocket connection. * @type BinaryType * @default 'blob' */ wsBinaryType: 'blob', /** * The default implementation of **getWebSocketReconnectDelay** for reconnecting after unexpected connection loss by the event code **Abnormal Closure**, **Service Restart** or **Try Again Later**. * @type {'full-jitter' | ((retryCount:number) => number)} * @default "full-jitter" */ wsReconnectDelay: 'full-jitter', }, /* Extension entrypoints */ /** @type {typeof defineExtension} */ defineExtension: null, /* DOM querying helpers */ /** @type {typeof find} */ find: null, /** @type {typeof findAll} */ findAll: null, /* Debugging */ /** @type {typeof logAll} */ logAll: null, /* Debugging */ /** * The logger htmx uses to log with. * @see https://htmx.org/api/#logger */ logger: null, /** @type {typeof logNone} */ logNone: null, /** @type {typeof removeEventListenerImpl} */ off: null, /** @type {typeof addEventListenerImpl} */ on: null, // Tsc madness here, assigning the functions directly results in an invalid TypeScript output, but reassigning is fine /* Event processing */ /** @type {typeof onLoadHelper} */ onLoad: null, /** @type {typeof parseInterval} */ parseInterval: null, /** @type {typeof processNode} */ process: null, /* DOM manipulation helpers */ /** @type {typeof removeElement} */ remove: null, /** @type {typeof removeClassFromElement} */ removeClass: null, /** @type {typeof removeExtension} */ removeExtension: null, /** @type {typeof swap} */ swap: null, /** @type {typeof takeClassForElement} */ takeClass: null, /** @type {typeof toggleClassOnElement} */ toggleClass: null, /** @type {typeof triggerEvent} */ trigger: null, /** * Returns the input values that would resolve for a given element via the htmx value resolution mechanism. * @param {Element} elt - The element to resolve values on. * @param {HttpVerb} type - The request type (e.g. **get** or **post**) non-GET's will include the enclosing form of the element. Defaults to **post**. * @returns {Object} * @see https://htmx.org/api/#values */ values: function (elt, type) { const inputValues = getInputValues(elt, type || 'post'); return inputValues.values; }, version: '2.0.3', }; // Tsc madness part 2 htmx.onLoad = onLoadHelper; htmx.process = processNode; htmx.on = addEventListenerImpl; htmx.off = removeEventListenerImpl; htmx.trigger = triggerEvent; htmx.ajax = ajaxHelper; htmx.find = find; htmx.findAll = findAll; htmx.closest = closest; htmx.remove = removeElement; htmx.addClass = addClassToElement; htmx.removeClass = removeClassFromElement; htmx.toggleClass = toggleClassOnElement; htmx.takeClass = takeClassForElement; htmx.swap = swap; htmx.defineExtension = defineExtension; htmx.removeExtension = removeExtension; htmx.logAll = logAll; htmx.logNone = logNone; htmx.parseInterval = parseInterval; htmx._ = internalEval; const internalAPI = { addTriggerHandler, bodyContains, canAccessLocalStorage, filterValues, findThisElement, getAttributeValue, getClosestAttributeValue, getClosestMatch, getExpressionVars, getHeaders, getInputValues, getInternalData, getSwapSpecification, getTarget, getTriggerSpecs, hasAttribute, makeFragment, makeSettleInfo, mergeObjects, oobSwap, querySelectorExt, settleImmediately, shouldCancel, swap, triggerErrorEvent, triggerEvent, withExtensions, }; const VERBS = ['get', 'post', 'put', 'delete', 'patch']; const VERB_SELECTOR = VERBS.map(function (verb) { return '[hx-' + verb + '], [data-hx-' + verb + ']'; }).join(', '); // = =================================================================== // Utilities // = =================================================================== /** * Parses an interval string consistent with the way htmx does. Useful for plugins that have timing-related attributes. * * Caution: Accepts an int followed by either **s** or **ms**. All other values use **parseFloat**. * @param {string} str - Timing string. * @returns {number|undefined} * @see https://htmx.org/api/#parseInterval */ function parseInterval(str) { if (str == undefined) { return undefined; } let interval = NaN; if (str.slice(-2) == 'ms') { interval = parseFloat(str.slice(0, -2)); } else if (str.slice(-1) == 's') { interval = parseFloat(str.slice(0, -1)) * 1000; } else if (str.slice(-1) == 'm') { interval = parseFloat(str.slice(0, -1)) * 1000 * 60; } else { interval = parseFloat(str); } return isNaN(interval) ? undefined : interval; } /** * @param {Node} elt * @param {string} name * @returns {(string | null)} */ function getRawAttribute(elt, name) { return elt instanceof Element && elt.getAttribute(name); } /** * @param {Element} elt * @param {string} qualifiedName * @returns {boolean} */ /** * Resolve with both hx and data-hx prefixes. * @param elt * @param qualifiedName */ function hasAttribute(elt, qualifiedName) { return !!elt.hasAttribute && (elt.hasAttribute(qualifiedName) || elt.hasAttribute('data-' + qualifiedName)); } /** * @param {Node} elt * @param {string} qualifiedName * @returns {(string | null)} */ function getAttributeValue(elt, qualifiedName) { return getRawAttribute(elt, qualifiedName) || getRawAttribute(elt, 'data-' + qualifiedName); } /** * @param {Node} elt * @returns {Node | null} */ function parentElt(elt) { const parent = elt.parentElement; if (!parent && elt.parentNode instanceof ShadowRoot) return elt.parentNode; return parent; } /** * @returns {Document} */ function getDocument() { return document; } /** * @param {Node} elt * @param {boolean} global * @returns {Node|Document} */ function getRootNode(elt, global) { return elt.getRootNode ? elt.getRootNode({ composed: global }) : getDocument(); } /** * @param {Node} elt * @param {(e:Node) => boolean} condition * @returns {Node | null} */ function getClosestMatch(elt, condition) { while (elt && !condition(elt)) { elt = parentElt(elt); } return elt || null; } /** * @param {Element} initialElement * @param {Element} ancestor * @param {string} attributeName * @returns {string|null} */ function getAttributeValueWithDisinheritance(initialElement, ancestor, attributeName) { const attributeValue = getAttributeValue(ancestor, attributeName); const disinherit = getAttributeValue(ancestor, 'hx-disinherit'); var inherit = getAttributeValue(ancestor, 'hx-inherit'); if (initialElement !== ancestor) { if (htmx.config.disableInheritance) { if (inherit && (inherit === '*' || inherit.split(' ').indexOf(attributeName) >= 0)) { return attributeValue; } else { return null; } } if (disinherit && (disinherit === '*' || disinherit.split(' ').indexOf(attributeName) >= 0)) { return 'unset'; } } return attributeValue; } /** * @param {Element} elt * @param {string} attributeName * @returns {string | null} */ function getClosestAttributeValue(elt, attributeName) { let closestAttr = null; getClosestMatch(elt, function (e) { return !!(closestAttr = getAttributeValueWithDisinheritance(elt, asElement(e), attributeName)); }); if (closestAttr !== 'unset') { return closestAttr; } } /** * @param {Node} elt * @param {string} selector * @returns {boolean} */ function matches(elt, selector) { // @ts-ignore: non-standard properties for browser compatibility // noinspection JSUnresolvedVariable const matchesFunction = elt instanceof Element && (elt.matches || elt.matchesSelector || elt.msMatchesSelector || elt.mozMatchesSelector || elt.webkitMatchesSelector || elt.oMatchesSelector); return !!matchesFunction && matchesFunction.call(elt, selector); } /** * @param {string} str * @returns {string} */ function getStartTag(str) { const tagMatcher = /<([a-z][^\0\t\n\f\r />]*)/i; const match = tagMatcher.exec(str); if (match) { return match[1].toLowerCase(); } else { return ''; } } /** * @param {string} resp * @returns {Document} */ function parseHTML(resp) { const parser = new DOMParser(); return parser.parseFromString(resp, 'text/html'); } /** * @param {DocumentFragment} fragment * @param {Node} elt */ function takeChildrenFor(fragment, elt) { while (elt.childNodes.length > 0) { fragment.append(elt.childNodes[0]); } } /** * @param {HTMLScriptElement} script * @returns {HTMLScriptElement} */ function duplicateScript(script) { const newScript = getDocument().createElement('script'); forEach(script.attributes, function (attr) { newScript.setAttribute(attr.name, attr.value); }); newScript.textContent = script.textContent; newScript.async = false; if (htmx.config.inlineScriptNonce) { newScript.nonce = htmx.config.inlineScriptNonce; } return newScript; } /** * @param {HTMLScriptElement} script * @returns {boolean} */ function isJavaScriptScriptNode(script) { return script.matches('script') && (script.type === 'text/javascript' || script.type === 'module' || script.type === ''); } /** * We have to make new copies of script tags that we are going to insert because * SOME browsers (not saying who, but it involves an element and an animal) don't * execute scripts created in