diff --git a/dist/htmx.js b/dist/htmx.js new file mode 100644 index 00000000..ba8ec346 --- /dev/null +++ b/dist/htmx.js @@ -0,0 +1,902 @@ +// noinspection JSUnusedAssignment +var HTMx = HTMx || (function () { + 'use strict'; + + var VERBS = ['get', 'post', 'put', 'delete', 'patch'] + + //==================================================================== + // Utilities + //==================================================================== + + function parseInterval(str) { + if (str === "null" || str === "false" || str === "") { + return null; + } else if (str.lastIndexOf("ms") === str.length - 2) { + return parseFloat(str.substr(0, str.length - 2)); + } else if (str.lastIndexOf("s") === str.length - 1) { + return parseFloat(str.substr(0, str.length - 1)) * 1000; + } else { + return parseFloat(str); + } + } + + function getRawAttribute(elt, name) { + return elt.getAttribute && elt.getAttribute(name); + } + + // resolve with both hx and data-hx prefixes + function getAttributeValue(elt, qualifiedName) { + return getRawAttribute(elt, qualifiedName) || getRawAttribute(elt, "data-" + qualifiedName); + } + + function parentElt(elt) { + return elt.parentElement; + } + + function getDocument() { + return document; + } + + function getClosestMatch(elt, condition) { + if (condition(elt)) { + return elt; + } else if (parentElt(elt)) { + return getClosestMatch(parentElt(elt), condition); + } else { + return null; + } + } + + function getClosestAttributeValue(elt, attributeName) { + var closestAttr = null; + getClosestMatch(elt, function (e) { + return closestAttr = getRawAttribute(e, attributeName); + }); + return closestAttr; + } + + function matches(elt, selector) { + // noinspection JSUnresolvedVariable + return (elt != null) &&(elt.matches || elt.matchesSelector || elt.msMatchesSelector || elt.mozMatchesSelector + || elt.webkitMatchesSelector || elt.oMatchesSelector).call(elt, selector); + } + + function closest (elt, selector) { + do if (elt == null || matches(elt, selector)) return elt; + while (elt = elt && parentElt(elt)); + } + + function makeFragment(resp) { + var range = getDocument().createRange(); + return range.createContextualFragment(resp); + } + + function isType(o, type) { + return Object.prototype.toString.call(o) === "[object " + type + "]"; + } + + function isFunction(o) { + return isType(o, "Function"); + } + + function isRawObject(o) { + return isType(o, "Object"); + } + + function getInternalData(elt) { + var dataProp = 'hx-data-internal'; + var data = elt[dataProp]; + if (!data) { + data = elt[dataProp] = {}; + } + return data; + } + + function toArray(object) { + var arr = []; + forEach(object, function(elt) { + arr.push(elt) + }); + return arr; + } + + function forEach(arr, func) { + for (var i = 0; i < arr.length; i++) { + func(arr[i]); + } + } + + function isScrolledIntoView(el) { + var rect = el.getBoundingClientRect(); + var elemTop = rect.top; + var elemBottom = rect.bottom; + return elemTop < window.innerHeight && elemBottom >= 0; + } + + function bodyContains(elt) { + return getDocument().body.contains(elt); + } + + //==================================================================== + // Node processing + //==================================================================== + + function getTarget(elt) { + var explicitTarget = getClosestMatch(elt, function(e){return getRawAttribute(e,"hx-target") !== null}); + + if (explicitTarget) { + var targetStr = getRawAttribute(explicitTarget, "hx-target"); + if (targetStr === "this") { + return explicitTarget; + } else { + return getDocument().querySelector(targetStr); + } + } else { + var data = getInternalData(elt); + if (data.boosted) { + return getDocument().body; + } else { + return elt; + } + } + } + + function directSwap(child) { + var swapDirect = getAttributeValue(child, 'hx-swap-direct'); + if (swapDirect) { + var target = getDocument().getElementById(getRawAttribute(child,'id')); + if (target) { + if (swapDirect === "merge") { + mergeInto(target, child); + } else { + var newParent = parentElt(target); + newParent.insertBefore(child, target); + newParent.removeChild(target); + return true; + } + } + } + return false; + } + + function processResponseNodes(parentNode, insertBefore, text, executeAfter, selector) { + var fragment = makeFragment(text); + var nodesToProcess; + if (selector) { + nodesToProcess = toArray(fragment.querySelectorAll(selector)); + } else { + nodesToProcess = toArray(fragment.childNodes); + } + forEach(nodesToProcess, function(child){ + if (!directSwap(child)) { + parentNode.insertBefore(child, insertBefore); + } + if (child.nodeType !== Node.TEXT_NODE) { + triggerEvent(child, 'load.hx', {parent:parentElt(child)}); + processNode(child); + } + }); + if(executeAfter) { + executeAfter.call(); + } + } + + function findMatch(elt, possible) { + for (var i = 0; i < possible.length; i++) { + var candidate = possible[i]; + if (elt.hasAttribute("id") && elt.id === candidate.id) { + return candidate; + } + if (!candidate.hasAttribute("id") && elt.tagName === candidate.tagName) { + return candidate; + } + } + return null; + } + + function cloneAttributes(mergeTo, mergeFrom) { + forEach(mergeTo.attributes, function (attr) { + if (!mergeFrom.hasAttribute(attr.name)) { + mergeTo.removeAttribute(attr.name) + } + }); + forEach(mergeFrom.attributes, function (attr) { + mergeTo.setAttribute(attr.name, attr.value); + }); + } + + function mergeChildren(mergeTo, mergeFrom) { + var oldChildren = toArray(mergeTo.children); + var marker = getDocument().createElement("span"); + mergeTo.insertBefore(marker, mergeTo.firstChild); + forEach(mergeFrom.childNodes, function (newChild) { + var match = findMatch(newChild, oldChildren); + if (match) { + while (marker.nextSibling && marker.nextSibling !== match) { + mergeTo.removeChild(marker.nextSibling); + } + mergeTo.insertBefore(marker, match.nextSibling); + mergeInto(match, newChild); + } else { + mergeTo.insertBefore(newChild, marker); + } + }); + while (marker.nextSibling) { + mergeTo.removeChild(marker.nextSibling); + } + mergeTo.removeChild(marker); + } + + function mergeInto(mergeTo, mergeFrom) { + cloneAttributes(mergeTo, mergeFrom); + mergeChildren(mergeTo, mergeFrom); + } + + function mergeResponse(target, resp, selector) { + var fragment = makeFragment(resp); + mergeInto(target, selector ? fragment.querySelector(selector) : fragment.firstElementChild); + } + + function swapResponse(target, elt, resp, after) { + + var swapStyle = getClosestAttributeValue(elt, "hx-swap"); + var selector = getClosestAttributeValue(elt, "hx-select"); + if (swapStyle === "merge") { + mergeResponse(target, resp, selector); + } else if (swapStyle === "outerHTML") { + processResponseNodes(parentElt(target), target, resp, after, selector); + parentElt(target).removeChild(target); + } else if (swapStyle === "prepend") { + processResponseNodes(target, target.firstChild, resp, after, selector); + } else if (swapStyle === "prependBefore") { + processResponseNodes(parentElt(target), target, resp, after, selector); + } else if (swapStyle === "append") { + processResponseNodes(target, null, resp, after, selector); + } else if (swapStyle === "appendAfter") { + processResponseNodes(parentElt(target), target.nextSibling, resp, after, selector); + } else { + target.innerHTML = ""; + processResponseNodes(target, null, resp, after, selector); + } + } + + function handleTrigger(elt, trigger) { + if (trigger) { + if (trigger.indexOf("{") === 0) { + var triggers = JSON.parse(trigger); + for (var eventName in triggers) { + if (triggers.hasOwnProperty(eventName)) { + var details = triggers[eventName]; + if (!isRawObject(details)) { + details = {"value": details} + } + triggerEvent(elt, eventName, details); + } + } + } else { + triggerEvent(elt, trigger, []); + } + } + } + + function getTrigger(elt) { + var explicitTrigger = getClosestAttributeValue(elt, 'hx-trigger'); + if (explicitTrigger) { + return explicitTrigger; + } else { + if (matches(elt, 'button')) { + return 'click'; + } else if (matches(elt, 'form')) { + return 'submit'; + } else if (matches(elt, 'input, textarea, select')) { + return 'change'; + } else { + return 'click'; + } + } + } + + function processClassList(elt, classList, operation) { + var values = classList.split(","); + forEach(values, function(value){ + var cssClass = ""; + var delay = 50; + var trimmedValue = value.trim(); + if (trimmedValue.indexOf(":") > 0) { + var split = trimmedValue.split(':'); + cssClass = split[0]; + delay = parseInterval(split[1]); + } else { + cssClass = trimmedValue; + } + setTimeout(function () { + elt.classList[operation].call(elt.classList, cssClass); + }, delay); + }); + } + + function processPolling(elt, verb, path) { + var trigger = getTrigger(elt); + var nodeData = getInternalData(elt); + if (trigger.trim().indexOf("every ") === 0) { + var args = trigger.split(/\s+/); + var intervalStr = args[1]; + if (intervalStr) { + var interval = parseInterval(intervalStr); + nodeData.timeout = setTimeout(function () { + if (bodyContains(elt)) { + issueAjaxRequest(elt, verb, path); + processPolling(elt, verb, getAttributeValue(elt, "hx-" + verb)); + } + }, interval); + } + } + } + + function isLocalLink(elt) { + return location.hostname === elt.hostname && + getRawAttribute(elt,'href') && + !getRawAttribute(elt,'href').startsWith("#") + } + + function boostElement(elt, nodeData, trigger) { + if ((elt.tagName === "A" && isLocalLink(elt)) || elt.tagName === "FORM") { + nodeData.boosted = true; + var verb, path; + if (elt.tagName === "A") { + verb = "get"; + path = getRawAttribute(elt, 'href'); + } else { + var rawAttribute = getRawAttribute(elt, "method"); + verb = rawAttribute ? rawAttribute.toLowerCase() : "get"; + path = getRawAttribute(elt, 'action'); + } + addEventListener(elt, verb, path, nodeData, trigger, true); + } + } + + function addEventListener(elt, verb, path, nodeData, trigger, cancel) { + var eventListener = function (evt) { + if(cancel) evt.preventDefault(); + var eventData = getInternalData(evt); + var elementData = getInternalData(elt); + if (!eventData.handled) { + eventData.handled = true; + if (getAttributeValue(elt, "hx-trigger-once") === "true") { + if (elementData.triggeredOnce) { + return; + } else { + elementData.triggeredOnce = true; + } + } + if (getAttributeValue(elt, "hx-trigger-changed-only") === "true") { + if (elementData.lastValue === elt.value) { + return; + } else { + elementData.lastValue = elt.value; + } + } + if (elementData.delayed) { + clearTimeout(elementData.delayed); + } + var eventDelay = getAttributeValue(elt, "hx-trigger-delay"); + var issueRequest = function(){ + issueAjaxRequest(elt, verb, path, evt.target); + } + if (eventDelay) { + elementData.delayed = setTimeout(issueRequest, parseInterval(eventDelay)); + } else { + issueRequest(); + } + } + }; + nodeData.trigger = trigger; + nodeData.eventListener = eventListener; + elt.addEventListener(trigger, eventListener); + } + + function initScrollHandler() { + if (!window['hxScrollHandler']) { + var scrollHandler = function() { + forEach(getDocument().querySelectorAll("[hx-trigger='reveal']"), function (elt) { + maybeReveal(elt); + }); + }; + window['hxScrollHandler'] = scrollHandler; + window.addEventListener("scroll", scrollHandler) + } + } + + function maybeReveal(elt) { + var nodeData = getInternalData(elt); + if (!nodeData.revealed && isScrolledIntoView(elt)) { + nodeData.revealed = true; + issueAjaxRequest(elt, nodeData.verb, nodeData.path); + } + } + + function maybeCloseSSESource(elt) { + if (!bodyContains(elt)) { + elt.sseSource.close(); + return true; + } + } + + function initSSESource(elt, sseSrc) { + var config = {withCredentials: true}; + triggerEvent(elt, "initSSE.mx", config) + var source = new EventSource(sseSrc); + source.onerror = function (e) { + triggerEvent(elt, "sseError.mx", {error:e, source:source}); + maybeCloseSSESource(elt); + }; + getInternalData(elt).sseSource = source; + } + + function processNode(elt) { + var nodeData = getInternalData(elt); + if (!nodeData.processed) { + nodeData.processed = true; + var trigger = getTrigger(elt); + var explicitAction = false; + forEach(VERBS, function(verb){ + var path = getAttributeValue(elt, 'hx-' + verb); + if (path) { + nodeData.path = path; + nodeData.verb = verb; + explicitAction = true; + if (trigger.indexOf("sse:") === 0) { + var sseEventName = trigger.substr(4); + var sseSource = getClosestMatch(elt, function(parent) {return parent.sseSource;}); + if (sseSource) { + var sseListener = function () { + if (!maybeCloseSSESource(sseSource)) { + if (bodyContains(elt)) { + issueAjaxRequest(elt, verb, path); + } else { + sseSource.sseSource.removeEventListener(sseEventName, sseListener); + } + } + }; + sseSource.sseSource.addEventListener(sseEventName, sseListener); + } else { + triggerEvent(elt, "noSSESourceError.mx") + } + } if (trigger === 'revealed') { + initScrollHandler(); + maybeReveal(elt); + } else if (trigger === 'load') { + if (!nodeData.loaded) { + nodeData.loaded = true; + issueAjaxRequest(elt, verb, path); + } + } else if (trigger.trim().indexOf('every ') === 0) { + nodeData.polling = true; + processPolling(elt, verb, path); + } else { + addEventListener(elt, verb, path, nodeData, trigger); + } + } + }); + if (!explicitAction && getClosestAttributeValue(elt, "hx-boost") === "true") { + boostElement(elt, nodeData, trigger); + } + var sseSrc = getAttributeValue(elt, 'hx-sse-source'); + if (sseSrc) { + initSSESource(elt, sseSrc); + } + var addClass = getAttributeValue(elt, 'hx-add-class'); + if (addClass) { + processClassList(elt, addClass, "add"); + } + var removeClass = getAttributeValue(elt, 'hx-remove-class'); + if (removeClass) { + processClassList(elt, removeClass, "remove"); + } + } + forEach(elt.children, function(child) { processNode(child) }); + } + + //==================================================================== + // Event/Log Support + //==================================================================== + + function sendError(elt, eventName, details) { + var errorURL = getClosestAttributeValue(elt, "hx-error-url"); + if (errorURL) { + var xhr = new XMLHttpRequest(); + xhr.open("POST", errorURL); + xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); + xhr.send(JSON.stringify({ "elt": elt.id, "event": eventName, "details" : details })); + } + } + + function makeEvent(eventName, details) { + var evt; + if (window.CustomEvent && typeof window.CustomEvent === 'function') { + evt = new CustomEvent(eventName, {detail: details}); + } else { + evt = getDocument().createEvent('CustomEvent'); + evt.initCustomEvent(eventName, true, true, details); + } + return evt; + } + + function triggerEvent(elt, eventName, details) { + details["elt"] = elt; + var event = makeEvent(eventName, details); + if (HTMx.logger) { + HTMx.logger(elt, eventName, details); + if (eventName.indexOf("Error") > 0) { + sendError(elt, eventName, details); + } + } + var eventResult = elt.dispatchEvent(event); + var allResult = elt.dispatchEvent(makeEvent("all.hx", {elt:elt, originalDetails:details, originalEvent: event})); + return eventResult && allResult; + } + + function addHTMxEventListener(arg1, arg2, arg3) { + var target, event, listener; + if (isFunction(arg1)) { + target = getDocument().body; + event = "all.hx"; + listener = arg1; + } else if (isFunction(arg2)) { + target = getDocument().body; + event = arg1; + listener = arg2; + } else { + target = arg1; + event = arg2; + listener = arg3; + } + return target.addEventListener(event, listener); + } + + //==================================================================== + // History Support + //==================================================================== + + function makeHistoryId() { + return Math.random().toString(36).substr(3, 9); + } + + function getHistoryElement() { + var historyElt = getDocument().getElementsByClassName('hx-history-element'); + if (historyElt.length > 0) { + return historyElt[0]; + } else { + return getDocument().body; + } + } + + function saveLocalHistoryData(historyData) { + localStorage.setItem('hx-history', JSON.stringify(historyData)); + } + + function getLocalHistoryData() { + var historyEntry = localStorage.getItem('hx-history'); + var historyData; + if (historyEntry) { + historyData = JSON.parse(historyEntry); + } else { + var initialId = makeHistoryId(); + historyData = {"current": initialId, "slots": [initialId]}; + saveLocalHistoryData(historyData); + } + return historyData; + } + + function newHistoryData() { + var historyData = getLocalHistoryData(); + var newId = makeHistoryId(); + var slots = historyData.slots; + if (slots.length > 20) { + var toEvict = slots.shift(); + localStorage.removeItem('hx-history-' + toEvict); + } + slots.push(newId); + historyData.current = newId; + saveLocalHistoryData(historyData); + } + + function updateCurrentHistoryContent() { + var elt = getHistoryElement(); + var historyData = getLocalHistoryData(); + history.replaceState({"hx-history-key": historyData.current}, getDocument().title, window.location.href); + localStorage.setItem('hx-history-' + historyData.current, elt.innerHTML); + } + + function restoreHistory(data) { + var historyKey = data['hx-history-key']; + var content = localStorage.getItem('hx-history-' + historyKey); + var elt = getHistoryElement(); + elt.innerHTML = ""; + processResponseNodes(elt, null, content); + } + + function shouldPush(elt) { + return getClosestAttributeValue(elt, "hx-push-url") === "true" || + (elt.tagName === "A" && getInternalData(elt).boosted); + } + + function snapshotForCurrentHistoryEntry(elt) { + if (shouldPush(elt)) { + // TODO event to allow de-initialization of HTML elements in target + updateCurrentHistoryContent(); + } + } + + function initNewHistoryEntry(elt, url) { + if (shouldPush(elt)) { + newHistoryData(); + history.pushState({}, "", url); + updateCurrentHistoryContent(); + } + } + + function addRequestIndicatorClasses(elt) { + mutateRequestIndicatorClasses(elt, "add"); + } + + function removeRequestIndicatorClasses(elt) { + mutateRequestIndicatorClasses(elt, "remove"); + } + + function mutateRequestIndicatorClasses(elt, action) { + var indicator = getClosestAttributeValue(elt, 'hx-indicator'); + if (indicator) { + var indicators = getDocument().querySelectorAll(indicator); + } else { + indicators = [elt]; + } + forEach(indicators, function(ic) { + ic.classList[action].call(ic.classList, "hx-show-indicator"); + }); + } + + //==================================================================== + // Input Value Processing + //==================================================================== + + function haveSeenNode(processed, elt) { + for (var i = 0; i < processed.length; i++) { + var node = processed[i]; + if (node.isSameNode(elt)) { + return true; + } + } + return false; + } + + function processInputValue(processed, values, elt) { + if (elt == null || haveSeenNode(processed, elt)) { + return; + } else { + processed.push(elt); + } + var name = getRawAttribute(elt,"name"); + var value = elt.value; + if (name && value) { + var current = values[name]; + if(current) { + if (Array.isArray(current)) { + current.push(value); + } else { + values[name] = [current, value]; + } + } else { + values[name] = value; + } + } + if (matches(elt, 'form')) { + var inputs = elt.elements; + forEach(inputs, function(input) { + processInputValue(processed, values, input); + }); + } + } + + function getInputValues(elt) { + var processed = []; + var values = {}; + // include the element itself + processInputValue(processed, values, elt); + + // include any explicit includes + var includes = getAttributeValue(elt, "hx-include"); + if (includes) { + var nodes = getDocument().querySelectorAll(includes); + forEach(nodes, function(node) { + processInputValue(processed, values, node); + }); + } + + // include the closest form + processInputValue(processed, values, closest(elt, 'form')); + return values; + } + + function appendParam(returnStr, name, realValue) { + if (returnStr !== "") { + returnStr += "&"; + } + returnStr += encodeURIComponent(name) + "=" + encodeURIComponent(realValue); + return returnStr; + } + + function urlEncode(values) { + var returnStr = ""; + for (var name in values) { + if (values.hasOwnProperty(name)) { + var value = values[name]; + if (Array.isArray(value)) { + forEach(value, function(v) { + returnStr = appendParam(returnStr, name, v); + }); + } else { + returnStr = appendParam(returnStr, name, value); + } + } + } + return returnStr; + } + + //==================================================================== + // Ajax + //==================================================================== + + function setHeader(xhr, name, value, noPrefix) { + xhr.setRequestHeader((noPrefix ? "" : "X-HX-") + name, value || ""); + } + + function issueAjaxRequest(elt, verb, path, eventTarget) { + var eltData = getInternalData(elt); + if (eltData.requestInFlight) { + return; + } else { + eltData.requestInFlight = true; + } + var endRequestLock = function(){ + eltData.requestInFlight = false + } + var target = getTarget(elt); + var promptQuestion = getClosestAttributeValue(elt, "hx-prompt"); + if (promptQuestion) { + var prompt = prompt(promptQuestion); + if(!triggerEvent(elt, 'prompt.hx', {prompt: prompt, target:target})) return endRequestLock(); + } + + var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm"); + if (confirmQuestion) { + if(!confirm(confirmQuestion)) return endRequestLock(); + } + + var xhr = new XMLHttpRequest(); + + var inputValues = getInputValues(elt); + if(!triggerEvent(elt, 'values.hx', {values: inputValues, target:target})) return endRequestLock(); + + // request type + if (verb === 'get') { + var noValues = Object.keys(inputValues).length === 0; + xhr.open('GET', path + (noValues ? "" : "?" + urlEncode(inputValues)), true); + } else { + xhr.open('POST', path, true); + setHeader(xhr,'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8', true); + if (verb !== 'post') { + setHeader(xhr, 'X-HTTP-Method-Override', verb.toUpperCase(), true); + } + } + + // TODO IE10 compatibility? + xhr.overrideMimeType("text/html"); + + // request headers + setHeader(xhr, "Request", "true"); + setHeader(xhr,"Trigger-Id", getRawAttribute(elt,"id")); + setHeader(xhr,"Trigger-Name", getRawAttribute(elt, "name")); + setHeader(xhr,"Target-Id", getRawAttribute(target,"id")); + setHeader(xhr,"Current-URL", getDocument().location.href); + if (prompt) { + setHeader(xhr,"Prompt", prompt); + } + if (eventTarget) { + setHeader(xhr,"Event-Target", getRawAttribute(eventTarget,"id")); + } + if (getDocument().activeElement) { + setHeader(xhr,"Active-Element", getRawAttribute(getDocument().activeElement,"id")); + // noinspection JSUnresolvedVariable + if (getDocument().activeElement.value) { + setHeader(xhr,"Active-Element-Value", getDocument().activeElement.value); + } + } + + xhr.onload = function () { + try { + if (!triggerEvent(elt, 'beforeOnLoad.hx', {xhr: xhr, target: target})) return; + snapshotForCurrentHistoryEntry(elt, path); + var trigger = this.getResponseHeader("X-HX-Trigger"); + handleTrigger(elt, trigger); + initNewHistoryEntry(elt, path); + if (this.status >= 200 && this.status < 400) { + // don't process 'No Content' response + if (this.status !== 204) { + // Success! + var resp = this.response; + if (!triggerEvent(elt, 'beforeSwap.hx', {xhr: xhr, target: target})) return; + target.classList.add("hx-swapping"); + var doSwap = function () { + try { + swapResponse(target, elt, resp, function () { + target.classList.remove("hx-swapping"); + updateCurrentHistoryContent(); + triggerEvent(elt, 'afterSwap.hx', {xhr: xhr, target: target}); + }); + } catch (e) { + triggerEvent(elt, 'swapError.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target}); + throw e; + } + }; + var swapDelayStr = getAttributeValue(elt, "hx-swap-delay"); + if (swapDelayStr) { + setTimeout(doSwap, parseInterval(swapDelayStr)) + } else { + doSwap(); + } + } + } else { + triggerEvent(elt, 'responseError.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target}); + } + } catch (e) { + triggerEvent(elt, 'onLoadError.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target}); + throw e; + } finally { + removeRequestIndicatorClasses(elt); + endRequestLock(); + triggerEvent(elt, 'afterOnLoad.hx', {xhr: xhr, response: xhr.response, status: xhr.status, target: target}); + } + } + xhr.onerror = function () { + removeRequestIndicatorClasses(elt);triggerEvent(elt, 'loadError.hx', {xhr:xhr}); + endRequestLock(); + } + if(!triggerEvent(elt, 'beforeRequest.hx', {xhr:xhr, values: inputValues, target:target})) return endRequestLock(); + addRequestIndicatorClasses(elt); + xhr.send(verb === 'get' ? null : urlEncode(inputValues)); + } + + //==================================================================== + // Initialization + //==================================================================== + + function ready(fn) { + if (getDocument().readyState !== 'loading') { + fn(); + } else { + getDocument().addEventListener('DOMContentLoaded', fn); + } + } + + // initialize the document + ready(function () { + processNode(getDocument().body); + window.onpopstate = function (event) { + restoreHistory(event.state); + }; + }) + + function internalEval(str){ + return eval(str); + } + + // Public API + return { + processElement: processNode, + on: addHTMxEventListener, + version: "0.0.1", + _:internalEval + } + } +)(); \ No newline at end of file diff --git a/dist/htmx.min.js b/dist/htmx.min.js new file mode 100644 index 00000000..79dc00d1 --- /dev/null +++ b/dist/htmx.min.js @@ -0,0 +1 @@ +var HTMx=HTMx||function(){"use strict";var n=["get","post","put","delete","patch"];function h(e){if(e==="null"||e==="false"||e===""){return null}else if(e.lastIndexOf("ms")===e.length-2){return parseFloat(e.substr(0,e.length-2))}else if(e.lastIndexOf("s")===e.length-1){return parseFloat(e.substr(0,e.length-1))*1e3}else{return parseFloat(e)}}function d(e,t){return e.getAttribute&&e.getAttribute(t)}function g(e,t){return d(e,t)||d(e,"data-"+t)}function s(e){return e.parentElement}function p(){return document}function l(e,t){if(t(e)){return e}else if(s(e)){return l(s(e),t)}else{return null}}function m(e,t){var r=null;l(e,function(e){return r=d(e,t)});return r}function u(e,t){return e!=null&&(e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector).call(e,t)}function a(e,t){do{if(e==null||u(e,t))return e}while(e=e&&s(e))}function f(e){var t=p().createRange();return t.createContextualFragment(e)}function t(e,t){return Object.prototype.toString.call(e)==="[object "+t+"]"}function o(e){return t(e,"Function")}function c(e){return t(e,"Object")}function x(e){var t="hx-data-internal";var r=e[t];if(!r){r=e[t]={}}return r}function v(e){var t=[];y(e,function(e){t.push(e)});return t}function y(e,t){for(var r=0;r=0}function S(e){return p().body.contains(e)}function b(e){var t=l(e,function(e){return d(e,"hx-target")!==null});if(t){var r=d(t,"hx-target");if(r==="this"){return t}else{return p().querySelector(r)}}else{var n=x(e);if(n.boosted){return p().body}else{return e}}}function w(e){var t=g(e,"hx-swap-direct");if(t){var r=p().getElementById(d(e,"id"));if(r){if(t==="merge"){C(r,e)}else{var n=s(r);n.insertBefore(e,r);n.removeChild(r);return true}}}return false}function E(t,r,e,n,i){var a=f(e);var o;if(i){o=v(a.querySelectorAll(i))}else{o=v(a.childNodes)}y(o,function(e){if(!w(e)){t.insertBefore(e,r)}if(e.nodeType!==Node.TEXT_NODE){J(e,"load.hx",{parent:s(e)});U(e)}});if(n){n.call()}}function T(e,t){for(var r=0;r0){var i=n.split(":");t=i[0];r=h(i[1])}else{t=n}setTimeout(function(){a.classList[o].call(a.classList,t)},r)})}function q(e,t,r){var n=M(e);var i=x(e);if(n.trim().indexOf("every ")===0){var a=n.split(/\s+/);var o=a[1];if(o){var s=h(o);i.timeout=setTimeout(function(){if(S(e)){le(e,t,r);q(e,t,g(e,"hx-"+t))}},s)}}}function I(e){return location.hostname===e.hostname&&d(e,"href")&&!d(e,"href").startsWith("#")}function R(e,t,r){if(e.tagName==="A"&&I(e)||e.tagName==="FORM"){t.boosted=true;var n,i;if(e.tagName==="A"){n="get";i=d(e,"href")}else{var a=d(e,"method");n=a?a.toLowerCase():"get";i=d(e,"action")}F(e,n,i,t,r,true)}}function F(a,o,s,e,t,u){var r=function(e){if(u)e.preventDefault();var t=x(e);var r=x(a);if(!t.handled){t.handled=true;if(g(a,"hx-trigger-once")==="true"){if(r.triggeredOnce){return}else{r.triggeredOnce=true}}if(g(a,"hx-trigger-changed-only")==="true"){if(r.lastValue===a.value){return}else{r.lastValue=a.value}}if(r.delayed){clearTimeout(r.delayed)}var n=g(a,"hx-trigger-delay");var i=function(){le(a,o,s,e.target)};if(n){r.delayed=setTimeout(i,h(n))}else{i()}}};e.trigger=t;e.eventListener=r;a.addEventListener(t,r)}function B(){if(!window["hxScrollHandler"]){var e=function(){y(p().querySelectorAll("[hx-trigger='reveal']"),function(e){X(e)})};window["hxScrollHandler"]=e;window.addEventListener("scroll",e)}}function X(e){var t=x(e);if(!t.revealed&&r(e)){t.revealed=true;le(e,t.verb,t.path)}}function k(e){if(!S(e)){e.sseSource.close();return true}}function P(t,e){var r={withCredentials:true};J(t,"initSSE.mx",r);var n=new EventSource(e);n.onerror=function(e){J(t,"sseError.mx",{error:e,source:n});k(t)};x(t).sseSource=n}function U(a){var o=x(a);if(!o.processed){o.processed=true;var s=M(a);var u=false;y(n,function(e){var t=g(a,"hx-"+e);if(t){o.path=t;o.verb=e;u=true;if(s.indexOf("sse:")===0){var r=s.substr(4);var n=l(a,function(e){return e.sseSource});if(n){var i=function(){if(!k(n)){if(S(a)){le(a,e,t)}else{n.sseSource.removeEventListener(r,i)}}};n.sseSource.addEventListener(r,i)}else{J(a,"noSSESourceError.mx")}}if(s==="revealed"){B();X(a)}else if(s==="load"){if(!o.loaded){o.loaded=true;le(a,e,t)}}else if(s.trim().indexOf("every ")===0){o.polling=true;q(a,e,t)}else{F(a,e,t,o,s)}}});if(!u&&m(a,"hx-boost")==="true"){R(a,o,s)}var e=g(a,"hx-sse-source");if(e){P(a,e)}var t=g(a,"hx-add-class");if(t){N(a,t,"add")}var r=g(a,"hx-remove-class");if(r){N(a,r,"remove")}}y(a.children,function(e){U(e)})}function j(e,t,r){var n=m(e,"hx-error-url");if(n){var i=new XMLHttpRequest;i.open("POST",n);i.setRequestHeader("Content-Type","application/json;charset=UTF-8");i.send(JSON.stringify({elt:e.id,event:t,details:r}))}}function D(e,t){var r;if(window.CustomEvent&&typeof window.CustomEvent==="function"){r=new CustomEvent(e,{detail:t})}else{r=p().createEvent("CustomEvent");r.initCustomEvent(e,true,true,t)}return r}function J(e,t,r){r["elt"]=e;var n=D(t,r);if(HTMx.logger){HTMx.logger(e,t,r);if(t.indexOf("Error")>0){j(e,t,r)}}var i=e.dispatchEvent(n);var a=e.dispatchEvent(D("all.hx",{elt:e,originalDetails:r,originalEvent:n}));return i&&a}function e(e,t,r){var n,i,a;if(o(e)){n=p().body;i="all.hx";a=e}else if(o(t)){n=p().body;i=e;a=t}else{n=e;i=t;a=r}return n.addEventListener(i,a)}function V(){return Math.random().toString(36).substr(3,9)}function _(){var e=p().getElementsByClassName("hx-history-element");if(e.length>0){return e[0]}else{return p().body}}function z(e){localStorage.setItem("hx-history",JSON.stringify(e))}function G(){var e=localStorage.getItem("hx-history");var t;if(e){t=JSON.parse(e)}else{var r=V();t={current:r,slots:[r]};z(t)}return t}function W(){var e=G();var t=V();var r=e.slots;if(r.length>20){var n=r.shift();localStorage.removeItem("hx-history-"+n)}r.push(t);e.current=t;z(e)}function K(){var e=_();var t=G();history.replaceState({"hx-history-key":t.current},p().title,window.location.href);localStorage.setItem("hx-history-"+t.current,e.innerHTML)}function Q(e){var t=e["hx-history-key"];var r=localStorage.getItem("hx-history-"+t);var n=_();n.innerHTML="";E(n,null,r)}function Y(e){return m(e,"hx-push-url")==="true"||e.tagName==="A"&&x(e).boosted}function Z(e){if(Y(e)){K()}}function $(e,t){if(Y(e)){W();history.pushState({},"",t);K()}}function ee(e){re(e,"add")}function te(e){re(e,"remove")}function re(e,t){var r=m(e,"hx-indicator");if(r){var n=p().querySelectorAll(r)}else{n=[e]}y(n,function(e){e.classList[t].call(e.classList,"hx-show-indicator")})}function ne(e,t){for(var r=0;r=200&&this.status<400){if(this.status!==204){var t=this.response;if(!J(i,"beforeSwap.hx",{xhr:f,target:s}))return;s.classList.add("hx-swapping");var r=function(){try{A(s,i,t,function(){s.classList.remove("hx-swapping");K();J(i,"afterSwap.hx",{xhr:f,target:s})})}catch(e){J(i,"swapError.hx",{xhr:f,response:f.response,status:f.status,target:s});throw e}};var n=g(i,"hx-swap-delay");if(n){setTimeout(r,h(n))}else{r()}}}else{J(i,"responseError.hx",{xhr:f,response:f.response,status:f.status,target:s})}}catch(e){J(i,"onLoadError.hx",{xhr:f,response:f.response,status:f.status,target:s});throw e}finally{te(i);o();J(i,"afterOnLoad.hx",{xhr:f,response:f.response,status:f.status,target:s})}};f.onerror=function(){te(i);J(i,"loadError.hx",{xhr:f});o()};if(!J(i,"beforeRequest.hx",{xhr:f,values:c,target:s}))return o();ee(i);f.send(e==="get"?null:se(c))}function fe(e){if(p().readyState!=="loading"){e()}else{p().addEventListener("DOMContentLoaded",e)}}fe(function(){U(p().body);window.onpopstate=function(e){Q(e.state)}});function ce(e){return eval(e)}return{processElement:U,on:e,version:"0.0.1",_:ce}}(); \ No newline at end of file diff --git a/package.json b/package.json index 151a9133..f5b4cb29 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,23 @@ { "name": "htmx", - "version": "0.0.1", "description": "HTML Extensions", - "main": "src/htmx.js", + "keywords": [ + "AJAX", + "HTML" + ], + "version": "0.0.1", + "homepage": "https://htmx.org/", + "bugs": { + "url": "https://github.com/bigskysoftware/htmx/issues" + }, + "license": "BSD 2-Clause", + "files": [ + "LICENSE", + "README.md", + "dist/*.js" + ], + "main": "dist/htmx.min.js", + "unpkg": "dist/htmx.min.js", "scripts": { "test": "mocha-chrome test/index.html", "dist": "cp src/htmx.js dist/ && npm run-script uglify && exit", @@ -12,16 +27,6 @@ "type": "git", "url": "git+https://github.com/bigskysoftware/htmx.git" }, - "keywords": [ - "AJAX", - "HTML" - ], - "author": "Carson Gross", - "license": "BSD 2-Clause", - "bugs": { - "url": "https://github.com/bigskysoftware/htmx/issues" - }, - "homepage": "https://htmx.org", "devDependencies": { "@11ty/eleventy": "^0.10.0", "@11ty/eleventy-plugin-syntaxhighlight": "^3.0.1", @@ -30,6 +35,5 @@ "mocha-chrome": "^2.2.0", "sinon": "^9.0.2", "uglify-js": "^3.9.1" - }, - "dependencies": {} + } }