Skip to main content
Ben Nadel at CFinNC 2009 (Raleigh, North Carolina) with: Bob Silverberg
Ben Nadel at CFinNC 2009 (Raleigh, North Carolina) with: Bob Silverberg

HTMX Extensions Have Access To An Extended API

By
Published in Comments (2)

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 as click or load).

  • bodyContains(elt) - checks to see if the given element is still in the current document.

  • canAccessLocalStorage() - tests whether or not calls to the localStorage API will throw an error.

  • filterValues(inputValues, elt) - filters a FormData object based on the closed hx-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 a data- 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) - accumulates hx-vals and hx-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 the hx-swap attribute on the given element.

  • getTarget(elt) - gets the most relevant hx-target reference for the given element.

  • getTriggerSpecs(elt) - parses the hx-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 the data- attribute is available as a fallback.

  • makeFragment(response) - parses the given HTML string into a document fragment node.

  • makeSettleInfo(target) - ???

  • mergeObjects(obj1, obj2) - copies the hasOwnProperty() 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 given error 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

16 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.

16,021 Comments

@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

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel