The idea behind htmlact
is to allow any HTML element to perform requests on the server for HTML fragments. These requests are specified via the data-request
attribute. We call request elements, elements that bear such an attribute.
In the following example:
<button data-request="POST /clicked" data-effect="element">Replace me</button>
The button is a request element. The request is performed when the event specified via the data-event
attribute occurs. For buttons, if unspecified, this is the click
event.
What happens exactly on a request is fully specified by the connection cycle which we describe next.
Each request element defines a connection cycle in which a few other elements take part. All these other elements are always defined via attributes of the request element. They can all point to the same element. In particular if they are not specified they mostly default to the request element itself.
data-request
attribute. It is the element that specifies the connection to the server.data-event-src
attribute. They are the elements whose events specified in the data-event
attribute triggers the request.data-query
attribute. These are the element that are looked up to devise the request's query data (transmitted in the request URL for GET
and HEAD
, or in the body for other methods).data-target
attribute. It specifies the relative location of the request response effect, that is where and how the HTML fragment from the server gets inserted in the page.data-feedback
. These are additional elements on which the connection cycle is feedback using CSS classes.Every request element on the page cycle through the following steps.
htmlact-request
htmlact-error
and stop here. Otherwise unclassify htmlact-request
and proceed.htmlact-out
for a while before being effectively removed. Elements that are introduced get transiently classified with htmlact-in
.If the request is:
Attributes of htmlact
use CSS selectors with querySelector
to gather query data and target response effects. The selector is applied on the request element, however CSS selectors have no syntax for addressing ancestors. We slightly extend the syntax to allow it because in many cases this eschews the need to use element identifiers which improves modularity – use with care, it can also improve obscurity.
We allow a CSS selector to be prefixed by a sequence of ancestor specifications which select the root on which the CSS selector is then applied. This provides full tree addressing: first move up to find an ancestor and then down by applying the CSS selector to it.
An ancestor specification is made of an optional element, optional classes and the made up :up
pseudo-class. The semantic is to move up from the element by following the up selectors from left-to-right and then apply the CSS selector on ancestor that was found.
Examples:
:scope > * # children (regular CSS selector) :scope * # descendent (regular CSS selector) :up # parent :up :up # parent's parent :up :up :scope > * # parent's parent's children .beet.root:up # ancestor with classes beet and root .beet:up .root:up # move to beet ancestor, then to root ancestor ul.beet.root:up # ul ancestor with classes beet and root div:up .beet # div ancestor, beet classified descendents
The full syntax as an RFC 5234 ABNF grammar is described as follows:
sel = *(up SP) css-selector up = [[el] *class] ":up" el = 1*(ALPHA) class = "." 1*(ALPHA) css-selector = … # See the CSS specification
These classes track connection cycle states.
htmlact-error
This class is applied on the request element and the feedback element whenever a request failed. This includes if the request returns a 4XX or 5XX response.
htmlact-in
and htmlact-in-parent
These classes are applied for a small amount of time (one render frame) when the effect is performed:
htmlact-in
is applied on the root of HTML trees that are inserted in the DOM by the effect.htmlact-in-parent
is applied on their parent.These classes are used to trigger CSS animations. For example to fade in an element in 250ms on insertion use:
.my-element.htmlact-in { opacity: 0; } .my-element { opacity: 1; transition: opacity 250ms; }
htmlact-out
and htmlact-out-parent
These classes are applied on elements (if any) that are removed by the effect just before it is performed:
htmlact-out
is applied on elements that will be removed.htmlact-out-parent
is on their parent.To determine the amount of time during which the classes are applied before the effect is performed, first the classes are applied on the elements. Then for each of these elements we take the maximum value of either CSS attribute --htmlact-out-duration
, animation-duration
or transition-duration
. The maximal value of all these durations defines the duration.
If the elements animating are descendent of those that are classified by htmlact-out
or htmlact-out-parent
, use the --htmlact-out-duration
attribute on the .htmlact-out
elements to set the time needed. For example the following ensures that the htmlact-out
and htmlact-out-parent
classes are maintained on the elements to be removed for 500ms before being effectively removed:
.htmlact-out { --htmlact-out-duration: 500ms }
htmlact-request
This class is applied on the request element and the feedback element(s) whenever a request to the server is ongoing.
This class can be used to trigger a CSS animation if the request is taking too much time. For example assuming you have a .spinner
in your request element, the following shows the spinner if the request is taking longer than 500ms.
.spinner { visibility: hidden; } .htmlact-request .spinner { animation: spin 1s linear 500ms infinite; } @keyframes spin { from { visibility: visible; } to { transform: rotate(360deg); }}
The only attribute required for an HTML element to be connected to your server is data-request which specifies the request to initiate the connection.
data-effect="<eff>"
The value <eff>
determines the way the HTML response is used on the target. This can be:
children
to replaces the children of the target (default).element
to replaces the target itself.beforebegin
to insert before the target.afterbegin
to insert before the first child of the target.beforeend
to insert after the last child of the target.afterend
to insert after the target.none
to discard the HTML response.event <ev>
to discard the HTML response but trigger an event named <ev>
on the targetIf unspecified this is children
.
data-event="<ev> <mod>*"
<ev>
is the name of the JavaScript event of the event source that triggers requests. <mod>
are modifiers for the event:
once
, the event is triggered only once.debounce:<dur>
, a debouncing time, the request only occurs after duration <time>
of the last event occurence.throttle:<dur>
, a throttling time, the request occurs immediatly but won't occur again before duration <dur>
.filter:<jsfun>
, name of a filtering function. The function is given the requesting element and the event, if it returns false
the event did not occur.If the attribute is unspecified this is:
submit
for form
elements.change
for input
, textarea
and select
.click
otherwise.data-event-src="<sel>"
The DOM element(s), as selected by <sel>
, whose events are being listened for to trigger a request. If unspecified this is the request element itself.
data-feedback="<sel>"
DOM elements in addition to target element on which the connection cycle is feedback with htmlact-request
and htmlact-error
.
data-query="<sel>"
The value of <sel>
is a selector which, when applied on the request element, determines the elements that are used to specify the query of the request. If unspecified this is the request element itself. See the syntax for selectors.
The final query of the request is determined by taking the query part of the requested URL and for each of the elements selected by <sel>
appending:
form
, the form data as gathered by FormData
.<value>
and the element has a name
property value <name>
, a <name>
to <value>
binding. If the element has no name
use "value"
for the <name>
.The query is transmitted in the URL on GET
or HEAD
requests and otherwise in the request body encoded with application/x-www-form-urlencoded
unless there is a file input in which case multipart/form-data
is used.
data-query-rescue="<bool>|force"
Use this to prevent users from leaving a page without performing the request if the query data changed.
If true
, the values determined by data-query
are snapshot on DOM insertion. If they still exist and they changed when the beforeunload
window event triggers the browser specific "leave page confirmation" modal is triggered.
If force
, this forces the event to trigger (e.g. if you performed validation on the server and put it back on page).
data-referrer-policy="<policy>"
The value of <policy>
determines the referrer-policy with which the request is made. It determines the value of the request's referer
header. If unspecified this is strict-origin
.
data-request="[<m>] <url>"
This attribute drives it all. If unspecified the element has no connection to the server and all other data-*
attributes are ignored.
<url>
is the URL to request, use the ws://
or wss://
scheme for a websocket connection. <m>
is the HTTP request method or SSE
to request a server sent events connection; defaults to GET
if unspecified.
data-target="<sel>"
The target DOM element, as selected by the first element of <sel>
, on which the request response performs its effect. If unspecified this is the request element itself.
These headers are automatically added on requests made by the request elements.
htmlact: true
Indicates the request is made by the htamlact
page driver.
referer: <url>
This is the standard HTTP referer
header. It indicates the URL of the page (without the fragment) that performs the request. Requests are made according to the data-referrer-policy
attribute of the request element.
If the HTML fragment of your response has relative URLs, they will be interpreted relative to <url>
once they are injected in the DOM.
The server should respond with an HTML fragment. This fragment is inserted in the DOM according to the data-target
and data-effect
values of the request attribute.
Additionally the response can use the following headers to control the client.
htmlact-location-push: <url>
Pushes location <url>
on the history stack.
htmlact-location-replace: <url>
Replaces current location by <url>
(without reloading). Has no effect if htmlact-location-push
is present.
htmlact-location-title: <pct-title>
Replaces the current title by the percent encoded title <pct-title>
. Mostly used in conjunction with htmlact-location-push
or htmlact-location-replace
.
htmlact-redirect: <url>
Redirects the page to <url>
. The body of the response is ignored by htmlact
page driver.
htmlact-reload: true
Reloads the page. The body of the response is ignored by the htmlact
page driver.