HTMX Extensions Have Access To An Extended API
The HTMX JavaScript framework exposes a public API that is a mixture of convenience methods, such as htmx.on()
for event-binding; and framework-specific methods, such as htmx.process()
for initializing externally-loaded HTML fragments. When creating an extension in HTMX, the extension's init()
method is passed an api
argument. At first, I thought this was just an abstracted reference to the aforementioned public API. But, upon further inspection, this reference contains an extended API to help specifically with HTMX extension authoring.
Here are the methods in this extension-oriented API along with my best attempt as a short description:
addTriggerHandler(elt, triggerSpec, nodeData, handler)
- attaches the event-bindings for the given trigger specification (such asclick
orload
).bodyContains(elt)
- checks to see if the given element is still in the current document.canAccessLocalStorage()
- tests whether or not calls to thelocalStorage
API will throw an error.filterValues(inputValues, elt)
- filters aFormData
object based on the closedhx-params
attribute.findThisElement(elt, attribute)
- walks up the DOM tree looking for the first element that has the given attribute.getAttributeValue(elt, qualifiedName)
- gets the value of the given attribute. If the attribute returns a Falsy value, the method attempts to access it with adata-
prefix as well.getClosestAttributeValue(elt, attributeName)
- walks up the DOM tree looking for the first value of the given attribute. Takes into account the HTMX rules for disinheritance.getClosestMatch(elt, condition)
- walks up the DOM tree looking for the first element that satisfies the given operator.getExpressionVars(elt)
- accumulateshx-vals
andhx-vars
for the given element.getHeaders(elt, target, prompt)
- gets the HTTP headers to include in an AJAX request triggered by the given element.getInputValues(elt, verb)
- gets the data to be submitted by the given HTTP verb.getInternalData(elt)
- returns the private HTMX data associated with the given node. This is where HTMX stores node-specific event bindings and other metadata that it needs to reference later.getSwapSpecification(elt, swapInfoOverride)
- parses thehx-swap
attribute on the given element.getTarget(elt)
- gets the most relevanthx-target
reference for the given element.getTriggerSpecs(elt)
- parses thehx-trigger
attribute on the given element.hasAttribute(elt, qualifiedName)
- checks to see if the given element has the given attribute. Also checks to see if thedata-
attribute is available as a fallback.makeFragment(response)
- parses the given HTML string into a document fragment node.makeSettleInfo(target)
- ???mergeObjects(obj1, obj2)
- copies thehasOwnProperty()
keys from the second object into the first object, and returns it.oobSwap(oobValue, oobElement, settleInfo, rootNode)
- applies the out-of-band (OOB) swap for the given element.querySelectorExt(eltOrSelector, selector)
- performs the HTMX-flavored DOM query relevant to the given node.settleImmediately(tasks)
- ???shouldCancel(evt, node)
- determines whether or not the.preventDefault()
method should be called on the given event, depending on whether or not this is an event that HTMX has to intercept.swap(target, content, swapSpec, swapOptions)
- implements complete swapping pipeline, including: focus and selection preservation, title updates, scroll, OOB swapping, normal swapping and settling.triggerErrorEvent(elt, eventName, detail)
- triggers an event with the givenerror
property.triggerEvent(elt, eventName, detail)
- dispatches an event on the given element.withExtensions(elt, toDo)
- executes the given operation for each extension that is active on the given node.
I'm particularly interested in getClosestAttributeValue()
for finding attribute values that are relevant to the current extension. Also, I think getInternalData()
might be very helpful for storing event and timer bindings. And, the querySelectorExt()
for performing selectors like closest
and previous
and next
could be very interesting.
As an aside, I had opened a discussion on GitHub asking about the use of this extended API; and, I've been assured that this is safe to use; and, is intentionally exposed for extension authors.
Reader Comments
Keep the HTMX Series going.
I'd like to see your thoughts on HTMX and Pusher WebSocket. Ether as an extension of shim JavaScript code.
I'd like to send template fragments down the WebSocket wire and have the fragment processed like it was "SWAP-OOB". I'm not sure Htmx is setup for that behavior, and I don't want to be working too hard against the tooling. I did make it work with some shim code, but I'd be interested in your thoughts.
@Peter,
That's a really interesting idea. I think it's the general premise behind the Datastar framework (which is inspired by the HTMX framework). I know very little about Datastar, but I think it's all driven by Server-Sent Events (SSE) and OOB swaps. If you squint hard enough, SSE is kind of like WebSockets in that it creates a kind of persistent connection (though, it's really just native long-polling).
Let me noodle on this. Right now, I'm just in the experimental phase where I'm trying to kick a bunch of tires. I haven't really built anything substantial with it yet (other than the Contacts App, what I based on the Hypermedia Systems book).
Post A Comment — ❤️ I'd Love To Hear From You! ❤️
Post a Comment →