` or ``).
To avoid this issue you can use a `template` tag to encapsulate these elements:
```html
Joe Smith
```
#### Selecting Content To Swap
If you want to select a subset of the response HTML to swap into the target, you can use the [hx-select](@/attributes/hx-select.md)
attribute, which takes a CSS selector and selects the matching elements from the response.
You can also pick out pieces of content for an out-of-band swap by using the [hx-select-oob](@/attributes/hx-select-oob.md)
attribute, which takes a list of element IDs to pick out and swap.
#### Preserving Content During A Swap
If there is content that you wish to be preserved across swaps (e.g. a video player that you wish to remain playing
even if a swap occurs) you can use the [hx-preserve](@/attributes/hx-preserve.md)
attribute on the elements you wish to be preserved.
### Parameters
By default, an element that causes a request will include its value if it has one. If the element is a form it
will include the values of all inputs within it.
As with HTML forms, the `name` attribute of the input is used as the parameter name in the request that htmx sends.
Additionally, if the element causes a non-`GET` request, the values of all the inputs of the associated form will be
included (typically this is the nearest enclosing form, but could be different if e.g. `` is used).
If you wish to include the values of other elements, you can use the [hx-include](@/attributes/hx-include.md) attribute
with a CSS selector of all the elements whose values you want to include in the request.
If you wish to filter out some parameters you can use the [hx-params](@/attributes/hx-params.md) attribute.
Finally, if you want to programmatically modify the parameters, you can use the [htmx:configRequest](@/events.md#htmx:configRequest)
event.
#### File Upload {#files}
If you wish to upload files via an htmx request, you can set the [hx-encoding](@/attributes/hx-encoding.md) attribute to
`multipart/form-data`. This will use a `FormData` object to submit the request, which will properly include the file
in the request.
Note that depending on your server-side technology, you may have to handle requests with this type of body content very
differently.
Note that htmx fires a `htmx:xhr:progress` event periodically based on the standard `progress` event during upload,
which you can hook into to show the progress of the upload.
See the [examples section](@/examples/_index.md) for more advanced form patterns, including [progress bars](@/examples/file-upload.md) and [error handling](@/examples/file-upload-input.md).
#### Extra Values
You can include extra values in a request using the [hx-vals](@/attributes/hx-vals.md) (name-expression pairs in JSON format) and
[hx-vars](@/attributes/hx-vars.md) attributes (comma-separated name-expression pairs that are dynamically computed).
### Confirming Requests {#confirming}
Often you will want to confirm an action before issuing a request. htmx supports the [`hx-confirm`](@/attributes/hx-confirm.md)
attribute, which allows you to confirm an action using a simple javascript dialog:
```html
Delete My Account
```
Using events you can implement more sophisticated confirmation dialogs. The [confirm example](@/examples/confirm.md)
shows how to use [sweetalert2](https://sweetalert2.github.io/) library for confirmation of htmx actions.
#### Confirming Requests Using Events
Another option to do confirmation with is via the [`htmx:confirm` event](@/events.md#htmx:confirm). This event
is fired on *every* trigger for a request (not just on elements that have a `hx-confirm` attribute) and can be used
to implement asynchronous confirmation of the request.
Here is an example using [sweet alert](https://sweetalert.js.org/guides/) on any element with a `confirm-with-sweet-alert='true'` attribute on it:
```javascript
document.body.addEventListener('htmx:confirm', function(evt) {
if (evt.target.matches("[confirm-with-sweet-alert='true']")) {
evt.preventDefault();
swal({
title: "Are you sure?",
text: "Are you sure you are sure?",
icon: "warning",
buttons: true,
dangerMode: true,
}).then((confirmed) => {
if (confirmed) {
evt.detail.issueRequest();
}
});
}
});
```
## Attribute Inheritance {#inheritance}
Most attributes in htmx are inherited: they apply to the element they are on as well as any children elements. This
allows you to "hoist" attributes up the DOM to avoid code duplication. Consider the following htmx:
```html
Delete My Account
Update My Account
```
Here we have a duplicate `hx-confirm` attribute. We can hoist this attribute to a parent element:
```html
Delete My Account
Update My Account
```
This `hx-confirm` attribute will now apply to all htmx-powered elements within it.
Sometimes you wish to undo this inheritance. Consider if we had a cancel button to this group, but didn't want it to
be confirmed. We could add an `unset` directive on it like so:
```html
Delete My Account
Update My Account
Cancel
```
The top two buttons would then show a confirm dialog, but the bottom cancel button would not.
Inheritance can be disabled on a per-element and per-attribute basis using the
[`hx-disinherit`](@/attributes/hx-disinherit.md) attribute.
If you wish to disable attribute inheritance entirely, you can set the `htmx.config.disableInheritance` configuration
variable to `true`. This will disable inheritance as a default, and allow you to specify inheritance explicitly
with the [`hx-inherit`](@/attributes/hx-inherit.md) attribute.
## Boosting
Htmx supports "boosting" regular HTML anchors and forms with the [hx-boost](@/attributes/hx-boost.md) attribute. This
attribute will convert all anchor tags and forms into AJAX requests that, by default, target the body of the page.
Here is an example:
```html
```
The anchor tag in this div will issue an AJAX `GET` request to `/blog` and swap the response into the `body` tag.
### Progressive Enhancement {#progressive_enhancement}
A feature of `hx-boost` is that it degrades gracefully if javascript is not enabled: the links and forms continue
to work, they simply don't use ajax requests. This is known as
[Progressive Enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement), and it allows
a wider audience to use your site's functionality.
Other htmx patterns can be adapted to achieve progressive enhancement as well, but they will require more thought.
Consider the [active search](@/examples/active-search.md) example. As it is written, it will not degrade gracefully:
someone who does not have javascript enabled will not be able to use this feature. This is done for simplicity’s sake,
to keep the example as brief as possible.
However, you could wrap the htmx-enhanced input in a form element:
```html
```
With this in place, javascript-enabled clients would still get the nice active-search UX, but non-javascript enabled
clients would be able to hit the enter key and still search. Even better, you could add a "Search" button as well.
You would then need to update the form with an `hx-post` that mirrored the `action` attribute, or perhaps use `hx-boost`
on it.
You would need to check on the server side for the `HX-Request` header to differentiate between an htmx-driven and a
regular request, to determine exactly what to render to the client.
Other patterns can be adapted similarly to achieve the progressive enhancement needs of your application.
As you can see, this requires more thought and more work. It also rules some functionality entirely out of bounds.
These tradeoffs must be made by you, the developer, with respect to your projects goals and audience.
[Accessibility](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility) is a concept
closely related to progressive enhancement. Using progressive enhancement techniques such as `hx-boost` will make your
htmx application more accessible to a wide array of users.
htmx-based applications are very similar to normal, non-AJAX driven web applications because htmx is HTML-oriented.
As such, the normal HTML accessibility recommendations apply. For example:
* Use semantic HTML as much as possible (i.e. the right tags for the right things)
* Ensure focus state is clearly visible
* Associate text labels with all form fields
* Maximize the readability of your application with appropriate fonts, contrast, etc.
## Web Sockets & SSE {#websockets-and-sse}
Web Sockets and Server Sent Events (SSE) are supported via extensions. Please see
the [SSE extension](/extensions/sse) and [WebSocket extension](/extensions/ws)
pages to learn more.
## History Support {#history}
Htmx provides a simple mechanism for interacting with the [browser history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API):
If you want a given element to push its request URL into the browser navigation bar and add the current state of the page
to the browser's history, include the [hx-push-url](@/attributes/hx-push-url.md) attribute:
```html
Blog
```
When a user clicks on this link, htmx will snapshot the current DOM and store it before it makes a request to /blog.
It then does the swap and pushes a new location onto the history stack.
When a user hits the back button, htmx will retrieve the old content from storage and swap it back into the target,
simulating "going back" to the previous state. If the location is not found in the cache, htmx will make an ajax
request to the given URL, with the header `HX-History-Restore-Request` set to true, and expects back the HTML needed
for the entire page. You should always set `htmx.config.historyRestoreAsHxRequest` to false to prevent the `HX-Request` header
which can then be safely used to respond with partials. Alternatively, if the `htmx.config.refreshOnHistoryMiss` config variable
is set to true, it will issue a hard browser refresh.
**NOTE:** If you push a URL into the history, you **must** be able to navigate to that URL and get a full page back!
A user could copy and paste the URL into an email, or new tab. Additionally, htmx will need the entire page when restoring
history if the page is not in the history cache.
### Specifying History Snapshot Element
By default, htmx will use the `body` to take and restore the history snapshot from. This is usually the right thing, but
if you want to use a narrower element for snapshotting you can use the [hx-history-elt](@/attributes/hx-history-elt.md)
attribute to specify a different one.
Careful: this element will need to be on all pages or restoring from history won't work reliably.
### Undoing DOM Mutations By 3rd Party Libraries
If you are using a 3rd party library and want to use the htmx history feature, you will need to clean up the DOM before
a snapshot is taken. Let's consider the [Tom Select](https://tom-select.js.org/) library, which makes select elements
a much richer user experience. Let's set up TomSelect to turn any input element with the `.tomselect` class into a rich
select element.
First we need to initialize elements that have the class in new content:
```javascript
htmx.onLoad(function (target) {
// find all elements in the new content that should be
// an editor and init w/ TomSelect
var editors = target.querySelectorAll(".tomselect")
.forEach(elt => new TomSelect(elt))
});
```
This will create a rich selector for all input elements that have the `.tomselect` class on it. However, it mutates
the DOM and we don't want that mutation saved to the history cache, since TomSelect will be reinitialized when the
history content is loaded back into the screen.
To deal with this, we need to catch the `htmx:beforeHistorySave` event and clean out the TomSelect mutations by calling
`destroy()` on them:
```javascript
htmx.on('htmx:beforeHistorySave', function() {
// find all TomSelect elements
document.querySelectorAll('.tomSelect')
.forEach(elt => elt.tomselect.destroy()) // and call destroy() on them
})
```
This will revert the DOM to the original HTML, thus allowing for a clean snapshot.
### Disabling History Snapshots
History snapshotting can be disabled for a URL by setting the [hx-history](@/attributes/hx-history.md) attribute to `false`
on any element in the current document, or any html fragment loaded into the current document by htmx. This can be used
to prevent sensitive data entering the localStorage cache, which can be important for shared-use / public computers.
History navigation will work as expected, but on restoration the URL will be requested from the server instead of the
local history cache.
## Requests & Responses {#requests}
Htmx expects responses to the AJAX requests it makes to be HTML, typically HTML fragments (although a full HTML
document, matched with a [hx-select](@/attributes/hx-select.md) tag can be useful too). Htmx will then swap the returned
HTML into the document at the target specified and with the swap strategy specified.
Sometimes you might want to do nothing in the swap, but still perhaps trigger a client side event ([see below](#response-headers)).
For this situation, by default, you can return a `204 - No Content` response code, and htmx will ignore the content of
the response.
In the event of an error response from the server (e.g. a 404 or a 501), htmx will trigger the [`htmx:responseError`](@/events.md#htmx:responseError)
event, which you can handle.
In the event of a connection error, the [`htmx:sendError`](@/events.md#htmx:sendError) event will be triggered.
### Configuring Response Handling {#response-handling}
You can configure the above behavior of htmx by mutating or replacing the `htmx.config.responseHandling` array. This
object is a collection of JavaScript objects defined like so:
```js
responseHandling: [
{code:"204", swap: false}, // 204 - No Content by default does nothing, but is not an error
{code:"[23]..", swap: true}, // 200 & 300 responses are non-errors and are swapped
{code:"[45]..", swap: false, error:true}, // 400 & 500 responses are not swapped and are errors
{code:"...", swap: false} // catch all for any other response code
]
```
When htmx receives a response it will iterate in order over the `htmx.config.responseHandling` array and test if the
`code` property of a given object, when treated as a Regular Expression, matches the current response. If an entry
does match the current response code, it will be used to determine if and how the response will be processed.
The fields available for response handling configuration on entries in this array are:
* `code` - a String representing a regular expression that will be tested against response codes.
* `swap` - `true` if the response should be swapped into the DOM, `false` otherwise
* `error` - `true` if htmx should treat this response as an error
* `ignoreTitle` - `true` if htmx should ignore title tags in the response
* `select` - A CSS selector to use to select content from the response
* `target` - A CSS selector specifying an alternative target for the response
* `swapOverride` - An alternative swap mechanism for the response
#### Configuring Response Handling Examples {#response-handling}
As an example of how to use this configuration, consider a situation when a server-side framework responds with a
[`422 - Unprocessable Entity`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422) response when validation errors occur. By default, htmx will ignore the response,
since it matches the Regular Expression `[45]..`.
Using the [meta config](#configuration-options) mechanism for configuring responseHandling, we could add the following
config:
```html
```
If you wanted to swap everything, regardless of HTTP response code, you could use this configuration:
```html
```
Finally, it is worth considering using the [Response Targets](/extensions/response-targets)
extension, which allows you to configure the behavior of response codes declaratively via attributes.
### CORS
When using htmx in a cross origin context, remember to configure your web
server to set Access-Control headers in order for htmx headers to be visible
on the client side.
- [Access-Control-Allow-Headers (for request headers)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers)
- [Access-Control-Expose-Headers (for response headers)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers)
[See all the request and response headers that htmx implements.](@/reference.md#request_headers)
### Request Headers
htmx includes a number of useful headers in requests:
| Header | Description |
|--------|-------------|
| `HX-Boosted` | indicates that the request is via an element using [hx-boost](@/attributes/hx-boost.md)
| `HX-Current-URL` | the current URL of the browser
| `HX-History-Restore-Request` | "true" if the request is for history restoration after a miss in the local history cache
| `HX-Prompt` | the user response to an [hx-prompt](@/attributes/hx-prompt.md)
| `HX-Request` | always "true" except on history restore requests if `htmx.config.historyRestoreAsHxRequest' disabled
| `HX-Target` | the `id` of the target element if it exists
| `HX-Trigger-Name` | the `name` of the triggered element if it exists
| `HX-Trigger` | the `id` of the triggered element if it exists
### Response Headers
htmx supports some htmx-specific response headers:
* [`HX-Location`](@/headers/hx-location.md) - allows you to do a client-side redirect that does not do a full page reload
* [`HX-Push-Url`](@/headers/hx-push-url.md) - pushes a new url into the history stack
* [`HX-Redirect`](@/headers/hx-redirect.md) - can be used to do a client-side redirect to a new location
* `HX-Refresh` - if set to "true" the client-side will do a full refresh of the page
* [`HX-Replace-Url`](@/headers/hx-replace-url.md) - replaces the current URL in the location bar
* `HX-Reswap` - allows you to specify how the response will be swapped. See [hx-swap](@/attributes/hx-swap.md) for possible values
* `HX-Retarget` - a CSS selector that updates the target of the content update to a different element on the page
* `HX-Reselect` - a CSS selector that allows you to choose which part of the response is used to be swapped in. Overrides an existing [`hx-select`](@/attributes/hx-select.md) on the triggering element
* [`HX-Trigger`](@/headers/hx-trigger.md) - allows you to trigger client-side events
* [`HX-Trigger-After-Settle`](@/headers/hx-trigger.md) - allows you to trigger client-side events after the settle step
* [`HX-Trigger-After-Swap`](@/headers/hx-trigger.md) - allows you to trigger client-side events after the swap step
For more on the `HX-Trigger` headers, see [`HX-Trigger` Response Headers](@/headers/hx-trigger.md).
Submitting a form via htmx has the benefit of no longer needing the [Post/Redirect/Get Pattern](https://en.wikipedia.org/wiki/Post/Redirect/Get).
After successfully processing a POST request on the server, you don't need to return a [HTTP 302 (Redirect)](https://en.wikipedia.org/wiki/HTTP_302). You can directly return the new HTML fragment.
Also the response headers above are not provided to htmx for processing with 3xx Redirect response codes like [HTTP 302 (Redirect)](https://en.wikipedia.org/wiki/HTTP_302). Instead, the browser will intercept the redirection internally and return the headers and response from the redirected URL. Where possible use alternative response codes like 200 to allow returning of these response headers.
### Request Order of Operations {#request-operations}
The order of operations in a htmx request are:
* The element is triggered and begins a request
* Values are gathered for the request
* The `htmx-request` class is applied to the appropriate elements
* The request is then issued asynchronously via AJAX
* Upon getting a response the target element is marked with the `htmx-swapping` class
* An optional swap delay is applied (see the [hx-swap](@/attributes/hx-swap.md) attribute)
* The actual content swap is done
* the `htmx-swapping` class is removed from the target
* the `htmx-added` class is added to each new piece of content
* the `htmx-settling` class is applied to the target
* A settle delay is done (default: 20ms)
* The DOM is settled
* the `htmx-settling` class is removed from the target
* the `htmx-added` class is removed from each new piece of content
You can use the `htmx-swapping` and `htmx-settling` classes to create
[CSS transitions](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions) between pages.
## Validation
Htmx integrates with the [HTML5 Validation API](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation)
and will not issue a request for a form if a validatable input is invalid. This is true for both AJAX requests as well as
WebSocket sends.
Htmx fires events around validation that can be used to hook in custom validation and error handling:
* `htmx:validation:validate` - called before an element's `checkValidity()` method is called. May be used to add in
custom validation logic
* `htmx:validation:failed` - called when `checkValidity()` returns false, indicating an invalid input
* `htmx:validation:halted` - called when a request is not issued due to validation errors. Specific errors may be found
in the `event.detail.errors` object
Non-form elements do not validate before they make requests by default, but you can enable validation by setting
the [`hx-validate`](@/attributes/hx-validate.md) attribute to "true".
### Validation Example
Here is an example of an input that uses the [`hx-on`](/attributes/hx-on) attribute to catch the
`htmx:validation:validate` event and require that the input have the value `foo`:
```html
```
Note that all client side validations must be re-done on the server side, as they can always be bypassed.
## Animations
Htmx allows you to use [CSS transitions](#css_transitions)
in many situations using only HTML and CSS.
Please see the [Animation Guide](@/examples/animations.md) for more details on the options available.
## Extensions
htmx provides an [extensions](/extensions) mechanism that allows you to customize the libraries' behavior.
Extensions [are defined in javascript](/extensions/building) and then enabled via
the [`hx-ext`](@/attributes/hx-ext.md) attribute.
Here is how you would install the [idiomorph](@extension/idiomorph) extension, which allows you to use the
[Idiomorph](https://github.com/bigskysoftware/idiomorph) DOM morphing algorithms for htmx swaps:
```html
...
Update Content
...
```
First the extension is included (it should be included *after* `htmx.js` is included), then the extension is referenced
by name via the `hx-ext` attribute. This enables you to then use the `morph` swap.
### Core Extensions
htmx supports a few "core" extensions, which are supported by the htmx development team:
* [head-support](/extensions/head-support) - support for merging head tag information (styles, etc.) in htmx requests |
* [htmx-1-compat](/extensions/htmx-1-compat) - restores htmx 1 defaults & functionality
* [idiomorph](/extensions/idiomorph) - supports the `morph` swap strategy using idiomorph
* [preload](/extensions/preload) - allows you to preload content for better performance
* [response-targets](/extensions/response-targets) - allows you to target elements based on HTTP response codes (e.g. `404`)
* [sse](/extensions/sse) - support for [Server Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)
* [ws](/extensions/ws) - support for [Web Sockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications)
You can see all available extensions on the [Extensions](/extensions) page.
### Creating Extensions
If you are interested in adding your own extension to htmx, please [see the extension docs](/extensions/building).
## Events & Logging {#events}
Htmx has an extensive [events mechanism](@/reference.md#events), which doubles as the logging system.
If you want to register for a given htmx event you can use
```js
document.body.addEventListener('htmx:load', function(evt) {
myJavascriptLib.init(evt.detail.elt);
});
```
or, if you would prefer, you can use the following htmx helper:
```javascript
htmx.on("htmx:load", function(evt) {
myJavascriptLib.init(evt.detail.elt);
});
```
The `htmx:load` event is fired every time an element is loaded into the DOM by htmx, and is effectively the equivalent
to the normal `load` event.
Some common uses for htmx events are:
### Initialize A 3rd Party Library With Events {#init_3rd_party_with_events}
Using the `htmx:load` event to initialize content is so common that htmx provides a helper function:
```javascript
htmx.onLoad(function(target) {
myJavascriptLib.init(target);
});
```
This does the same thing as the first example, but is a little cleaner.
### Configure a Request With Events {#config_request_with_events}
You can handle the [`htmx:configRequest`](@/events.md#htmx:configRequest) event in order to modify an AJAX request before it is issued:
```javascript
document.body.addEventListener('htmx:configRequest', function(evt) {
evt.detail.parameters['auth_token'] = getAuthToken(); // add a new parameter into the request
evt.detail.headers['Authentication-Token'] = getAuthToken(); // add a new header into the request
});
```
Here we add a parameter and header to the request before it is sent.
### Modifying Swapping Behavior With Events {#modifying_swapping_behavior_with_events}
You can handle the [`htmx:beforeSwap`](@/events.md#htmx:beforeSwap) event in order to modify the swap behavior of htmx:
```javascript
document.body.addEventListener('htmx:beforeSwap', function(evt) {
if(evt.detail.xhr.status === 404){
// alert the user when a 404 occurs (maybe use a nicer mechanism than alert())
alert("Error: Could Not Find Resource");
} else if(evt.detail.xhr.status === 422){
// allow 422 responses to swap as we are using this as a signal that
// a form was submitted with bad data and want to rerender with the
// errors
//
// set isError to false to avoid error logging in console
evt.detail.shouldSwap = true;
evt.detail.isError = false;
} else if(evt.detail.xhr.status === 418){
// if the response code 418 (I'm a teapot) is returned, retarget the
// content of the response to the element with the id `teapot`
evt.detail.shouldSwap = true;
evt.detail.target = htmx.find("#teapot");
}
});
```
Here we handle a few [400-level error response codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses)
that would normally not do a swap in htmx.
### Event Naming {#event_naming}
Note that all events are fired with two different names
* Camel Case
* Kebab Case
So, for example, you can listen for `htmx:afterSwap` or for `htmx:after-swap`. This facilitates interoperability
with other libraries. [Alpine.js](https://github.com/alpinejs/alpine/), for example, requires kebab case.
### Logging
If you set a logger at `htmx.logger`, every event will be logged. This can be very useful for troubleshooting:
```javascript
htmx.logger = function(elt, event, data) {
if(console) {
console.log(event, elt, data);
}
}
```
## Debugging
Declarative and event driven programming with htmx (or any other declarative language) can be a wonderful and highly productive
activity, but one disadvantage when compared with imperative approaches is that it can be trickier to debug.
Figuring out why something *isn't* happening, for example, can be difficult if you don't know the tricks.
Well, here are the tricks:
The first debugging tool you can use is the `htmx.logAll()` method. This will log every event that htmx triggers and
will allow you to see exactly what the library is doing.
```javascript
htmx.logAll();
```
Of course, that won't tell you why htmx *isn't* doing something. You might also not know *what* events a DOM
element is firing to use as a trigger. To address this, you can use the
[`monitorEvents()`](https://developers.google.com/web/updates/2015/05/quickly-monitor-events-from-the-console-panel) method available in the
browser console:
```javascript
monitorEvents(htmx.find("#theElement"));
```
This will spit out all events that are occurring on the element with the id `theElement` to the console, and allow you
to see exactly what is going on with it.
Note that this *only* works from the console, you cannot embed it in a script tag on your page.
Finally, push come shove, you might want to just debug `htmx.js` by loading up the unminimized version. It's
about 2500 lines of javascript, so not an insurmountable amount of code. You would most likely want to set a break
point in the `issueAjaxRequest()` and `handleAjaxResponse()` methods to see what's going on.
And always feel free to jump on the [Discord](https://htmx.org/discord) if you need help.
### Creating Demos
Sometimes, in order to demonstrate a bug or clarify a usage, it is nice to be able to use a javascript snippet
site like [jsfiddle](https://jsfiddle.net/). To facilitate easy demo creation, htmx hosts a demo script
site that will install:
* htmx
* hyperscript
* a request mocking library
Simply add the following script tag to your demo/fiddle/whatever:
```html
```
This helper allows you to add mock responses by adding `template` tags with a `url` attribute to indicate which URL.
The response for that url will be the innerHTML of the template, making it easy to construct mock responses. You can
add a delay to the response with a `delay` attribute, which should be an integer indicating the number of milliseconds
to delay
You may embed simple expressions in the template with the `${}` syntax.
Note that this should only be used for demos and is in no way guaranteed to work for long periods of time
as it will always be grabbing the latest versions htmx and hyperscript!
#### Demo Example
Here is an example of the code in action:
```html
Count Up
${globalInt++}
```
## Scripting {#scripting}
While htmx encourages a hypermedia approach to building web applications, it offers many options for client scripting. Scripting is included in the REST-ful description of web architecture, see: [Code-On-Demand](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_7). As much as is feasible, we recommend a [hypermedia-friendly](/essays/hypermedia-friendly-scripting) approach to scripting in your web application:
* [Respect HATEOAS](/essays/hypermedia-friendly-scripting#prime_directive)
* [Use events to communicate between components](/essays/hypermedia-friendly-scripting#events)
* [Use islands to isolate non-hypermedia components from the rest of your application](/essays/hypermedia-friendly-scripting#islands)
* [Consider inline scripting](/essays/hypermedia-friendly-scripting#inline)
The primary integration point between htmx and scripting solutions is the [events](#events) that htmx sends and can
respond to. See the SortableJS example in the [3rd Party Javascript](#3rd-party) section for a good template for
integrating a JavaScript library with htmx via events.
Scripting solutions that pair well with htmx include:
* [VanillaJS](http://vanilla-js.com/) - Simply using the built-in abilities of JavaScript to hook in event handlers to
respond to the events htmx emits can work very well for scripting. This is an extremely lightweight and increasingly
popular approach.
* [AlpineJS](https://alpinejs.dev/) - Alpine.js provides a rich set of tools for creating sophisticated front end scripts,
including reactive programming support, while still remaining extremely lightweight. Alpine encourages the "inline scripting"
approach that we feel pairs well with htmx.
* [jQuery](https://jquery.com/) - Despite its age and reputation in some circles, jQuery pairs very well with htmx, particularly
in older code-bases that already have a lot of jQuery in them.
* [hyperscript](https://hyperscript.org) - Hyperscript is an experimental front-end scripting language created by the same
team that created htmx. It is designed to embed well in HTML and both respond to and create events, and pairs very well
with htmx.
We have an entire chapter entitled ["Client-Side Scripting"](https://hypermedia.systems/client-side-scripting/) in [our
book](https://hypermedia.systems) that looks at how scripting can be integrated into your htmx-based application.
### [The `hx-on*` Attributes](#hx-on)
HTML allows the embedding of inline scripts via the [`onevent` properties](https://developer.mozilla.org/en-US/docs/Web/Events/Event_handlers#using_onevent_properties),
such as `onClick`:
```html
Click Me!
```
This feature allows scripting logic to be co-located with the HTML elements the logic applies to, giving good
[Locality of Behaviour (LoB)](/essays/locality-of-behaviour). Unfortunately, HTML only allows `on*` attributes for a fixed
number of [specific DOM events](https://www.w3schools.com/tags/ref_eventattributes.asp) (e.g. `onclick`) and
doesn't provide a generalized mechanism for responding to arbitrary events on elements.
In order to address this shortcoming, htmx offers [`hx-on*`](/attributes/hx-on) attributes. These attributes allow
you to respond to any event in a manner that preserves the LoB of the standard `on*` properties.
If we wanted to respond to the `click` event using an `hx-on` attribute, we would write this:
```html
Click Me!
```
So, the string `hx-on`, followed by a colon (or a dash), then by the name of the event.
For a `click` event, of course, we would recommend sticking with the standard `onclick` attribute. However, consider an
htmx-powered button that wishes to add a parameter to a request using the `htmx:config-request` event. This would not
be possible using a standard `on*` property, but it can be done using the `hx-on:htmx:config-request` attribute:
```html
Post Me!
```
Here the `example` parameter is added to the `POST` request before it is issued, with the value 'Hello Scripting!'.
The `hx-on*` attributes are a very simple mechanism for generalized embedded scripting. It is _not_ a replacement for more
fully developed front-end scripting solutions such as AlpineJS or hyperscript. It can, however, augment a VanillaJS-based
approach to scripting in your htmx-powered application.
Note that HTML attributes are *case insensitive*. This means that, unfortunately, events that rely on capitalization/
camel casing, cannot be responded to. If you need to support camel case events we recommend using a more fully
functional scripting solution such as AlpineJS or hyperscript. htmx dispatches all its events in both camelCase and in
kebab-case for this very reason.
### 3rd Party Javascript {#3rd-party}
Htmx integrates fairly well with third party libraries. If the library fires events on the DOM, you can use those events to
trigger requests from htmx.
A good example of this is the [SortableJS demo](@/examples/sortable.md):
```html
```
With Sortable, as with most javascript libraries, you need to initialize content at some point.
In jquery you might do this like so:
```javascript
$(document).ready(function() {
var sortables = document.body.querySelectorAll(".sortable");
for (var i = 0; i < sortables.length; i++) {
var sortable = sortables[i];
new Sortable(sortable, {
animation: 150,
ghostClass: 'blue-background-class'
});
}
});
```
In htmx, you would instead use the `htmx.onLoad` function, and you would select only from the newly loaded content,
rather than the entire document:
```js
htmx.onLoad(function(content) {
var sortables = content.querySelectorAll(".sortable");
for (var i = 0; i < sortables.length; i++) {
var sortable = sortables[i];
new Sortable(sortable, {
animation: 150,
ghostClass: 'blue-background-class'
});
}
})
```
This will ensure that as new content is added to the DOM by htmx, sortable elements are properly initialized.
If javascript adds content to the DOM that has htmx attributes on it, you need to make sure that this content
is initialized with the `htmx.process()` function.
For example, if you were to fetch some data and put it into a div using the `fetch` API, and that HTML had
htmx attributes in it, you would need to add a call to `htmx.process()` like this:
```js
let myDiv = document.getElementById('my-div')
fetch('http://example.com/movies.json')
.then(response => response.text())
.then(data => { myDiv.innerHTML = data; htmx.process(myDiv); } );
```
Some 3rd party libraries create content from HTML template elements. For instance, Alpine JS uses the `x-if`
attribute on templates to add content conditionally. Such templates are not initially part of the DOM and,
if they contain htmx attributes, will need a call to `htmx.process()` after they are loaded. The following
example uses Alpine's `$watch` function to look for a change of value that would trigger conditional content:
```html
```
#### Web Components {#web-components}
Please see the [Web Components Examples](@/examples/web-components.md) page for examples on how to integrate htmx
with web components.
## Caching
htmx works with standard [HTTP caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching)
mechanisms out of the box.
If your server adds the
[`Last-Modified`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)
HTTP response header to the response for a given URL, the browser will automatically add the
[`If-Modified-Since`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since)
request HTTP header to the next requests to the same URL. Be mindful that if
your server can render different content for the same URL depending on some other
headers, you need to use the [`Vary`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#vary)
response HTTP header. For example, if your server renders the full HTML when the
`HX-Request` header is missing or `false`, and it renders a fragment of that HTML
when `HX-Request: true`, you need to add `Vary: HX-Request`. That causes the cache to be
keyed based on a composite of the response URL and the `HX-Request` request header —
rather than being based just on the response URL. Always disable `htmx.config.historyRestoreAsHxRequest`
so that these history full HTML requests are not cached with partial fragment responses.
If you are unable (or unwilling) to use the `Vary` header, you can alternatively set the configuration parameter
`getCacheBusterParam` to `true`. If this configuration variable is set, htmx will include a cache-busting parameter
in `GET` requests that it makes, which will prevent browsers from caching htmx-based and non-htmx based responses
in the same cache slot.
htmx also works with [`ETag`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag)
as expected. Be mindful that if your server can render different content for the same
URL (for example, depending on the value of the `HX-Request` header), the server needs
to generate a different `ETag` for each content.
## Security
htmx allows you to define logic directly in your DOM. This has a number of advantages, the largest being
[Locality of Behavior](@/essays/locality-of-behaviour.md), which makes your system easier to understand and
maintain.
A concern with this approach, however, is security: since htmx increases the expressiveness of HTML, if a malicious
user is able to inject HTML into your application, they can leverage this expressiveness of htmx to malicious
ends.
### Rule 1: Escape All User Content
The first rule of HTML-based web development has always been: *do not trust input from the user*. You should escape all
3rd party, untrusted content that is injected into your site. This is to prevent, among other issues,
[XSS attacks](https://en.wikipedia.org/wiki/Cross-site_scripting).
There is extensive documentation on XSS and how to prevent it on the excellent [OWASP Website](https://owasp.org/www-community/attacks/xss/),
including a [Cross Site Scripting Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).
The good news is that this is a very old and well understood topic, and the vast majority of server-side templating languages
support [automatic escaping](https://docs.djangoproject.com/en/4.2/ref/templates/language/#automatic-html-escaping) of
content to prevent just such an issue.
That being said, there are times people choose to inject HTML more dangerously, often via some sort of `raw()`
mechanism in their templating language. This can be done for good reasons, but if the content being injected is coming
from a 3rd party then it _must_ be scrubbed, including removing attributes starting with `hx-` and `data-hx`, as well as
inline `