Skip to content

Commit

Permalink
Added support for 5xx-style wildcards in response-targets extension
Browse files Browse the repository at this point in the history
  • Loading branch information
siefca committed Jul 22, 2023
1 parent a140dab commit a04bae0
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 7 deletions.
20 changes: 16 additions & 4 deletions src/ext/response-targets.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,19 @@
return api.querySelectorExt(elt, targetStr);
}
} else {
for (let l = targetAttr.length - 1; l > targetAttrMinLen; l--) {
targetAttr = targetAttr.substring(0, l) + '*';
targetStr = api.getClosestAttributeValue(elt, targetAttr);
if (targetStr) break;
let wildcardStr = htmx.config.responseTargetWildcard;
if (wildcardStr) {
for (let l = targetAttr.length - 1, wStrBuf = wildcardStr; l > targetAttrMinLen; l--, wStrBuf += wildcardStr) {
targetAttr = targetAttr.substring(0, l) + wStrBuf;
targetStr = api.getClosestAttributeValue(elt, targetAttr);
if (targetStr) break;
}
} else {
for (let l = targetAttr.length - 1; l > targetAttrMinLen; l--) {
targetAttr = targetAttr.substring(0, l) + '*';
targetStr = api.getClosestAttributeValue(elt, targetAttr);
if (targetStr) break;
}
}
}

Expand Down Expand Up @@ -71,6 +80,9 @@
if (htmx.config.responseTargetPrefersRetargetHeader === undefined) {
htmx.config.responseTargetPrefersRetargetHeader = true;
}
if (htmx.config.responseTargetWildcard === undefined) {
htmx.config.responseTargetWildcard = false;
}
},

/**
Expand Down
13 changes: 13 additions & 0 deletions test/ext/response-targets.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ describe("response-targets extension", function() {
div1.innerHTML.should.equal("Not found!");
});

it('targets an adjacent element properly with custom wildcard', function()
{
var prevWildcard = htmx.config.responseTargetWildcard;
htmx.config.responseTargetWildcard = 'x';
this.server.respondWith("GET", "/test", [404, {}, "Not found!"]);
var btn = make('<button hx-ext="response-targets" hx-target-4xx="#d1" hx-get="/test">Click Me!</button>')
var div1 = make('<div id="d1"></div>')
btn.click();
this.server.respond();
htmx.config.responseTargetWildcard = prevWildcard;
div1.innerHTML.should.equal("Not found!");
});

it('targets a parent element properly', function()
{
this.server.respondWith("GET", "/test", [404, {}, "Not found!"]);
Expand Down
34 changes: 31 additions & 3 deletions www/content/extensions/response-targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ The value of each attribute can be:
is set and target exists. It is not extracting target's value from the header but
trusts it was set by HTMX core logic.

* Normally, a single asterisk character (`*`) placed at the end of an attribute name
can be used as an optional wildcard to create target for multiple status codes
(e.g. `hx-target-5*` will match any code starting with the number `5`). You can
change that behavior by setting a configuration flag
`htmx.config.responseTargetWildcard` to a string which will substitute each digit
that cannot be found (effectively padding the `hx-target-…` attribute name). See
the 'Wildcard resolution' section below for more details.

* Normally, any target which is already established by HTMX built-in functions or
extensions called before will be overwritten if a matching `hx-target-…` tag is
found. You may change it by using a configuration flag
Expand Down Expand Up @@ -88,10 +96,10 @@ for 404 (not found) response, and yet another for all 5xx response codes:

## Wildcard resolution

When status response code does not match existing `hx-target-[CODE]` attribute name
When status response code does not match existing `hx-target-[CODE]` attribute name
then its numeric part expressed as a string is trimmed with last character being
replaced with the asterisk (`*`). This lookup process continues until the attribute
is found or there are no more digits.
replaced with the asterisk (`*`). The lookup process continues until the attribute is
found or there are no more digits.

For example, if a browser receives 404 error code, the following attribute names will
be looked up (in the given order):
Expand All @@ -101,6 +109,26 @@ be looked up (in the given order):
* `hx-target-4*`
* `hx-target-*`.

However, when `htmx.config.responseTargetWildcard` configuration option is in place,
then the given string is used to replace **each digit at a time** when there was no
precise match. For this option being set to `x` the lookup will be:

* `hx-target-404`
* `hx-target-40x`
* `hx-target-4xx`
* `hx-target-xxx`.

Note that if the option `htmx.config.responseTargetWildcard` is manually set to `*`
the lookup will be:

* `hx-target-404`
* `hx-target-40*`
* `hx-target-4**`
* `hx-target-***`.

To re-enable the default behavior (a single-asterisk lookup), you will have to set it
to `false` or another falsy value.

## Notes

* `hx-target-…` is inherited and can be placed on a parent element.
Expand Down

0 comments on commit a04bae0

Please sign in to comment.