Skip to content

Commit

Permalink
Support hx-target-5xx syntax in response-targets extension (bigskysof…
Browse files Browse the repository at this point in the history
  • Loading branch information
spiffytech authored and infogulch committed Aug 22, 2023
1 parent 2eb513c commit 02f3027
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 27 deletions.
64 changes: 38 additions & 26 deletions src/ext/response-targets.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,55 @@
/** @type {import("../htmx").HtmxInternalApi} */
var api;

const targetAttrPrefix = 'hx-target-';
const targetAttrMinLen = targetAttrPrefix.length - 1;
var attrPrefix = 'hx-target-';

/**
* @param {HTMLElement} elt
* @param {number} respCode
* @returns {HTMLElement | null}
*/
function getRespCodeTarget(elt, respCode) {
if (!elt || !respCode) return null;
function getRespCodeTarget(elt, respCodeNumber) {
if (!elt || !respCodeNumber) return null;

var targetAttr = targetAttrPrefix + respCode;
var targetStr = api.getClosestAttributeValue(elt, targetAttr);
var respCode = respCodeNumber.toString();

if (targetStr) {
if (targetStr === "this") {
return api.findThisElement(elt, targetAttr);
} else {
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;
}
}
// '*' is the original syntax, as the obvious character for a wildcard.
// The 'x' alternative was added for maximum compatibility with HTML
// templating engines, due to ambiguity around which characters are
// supported in HTML attributes.
//
// Start with the most specific possible attribute and generalize from
// there.
var attrPossibilities = [
respCode,

respCode.substr(0, 2) + '*',
respCode.substr(0, 2) + 'x',

if (targetStr) {
if (targetStr === "this") {
return api.findThisElement(elt, targetAttr);
} else {
return api.querySelectorExt(elt, targetStr);
respCode.substr(0, 1) + '*',
respCode.substr(0, 1) + 'x',
respCode.substr(0, 1) + '**',
respCode.substr(0, 1) + 'xx',

'*',
'x',
'***',
'xxx',
];

for (var i = 0; i < attrPossibilities.length; i++) {
var attr = attrPrefix + attrPossibilities[i];
var attrValue = api.getClosestAttributeValue(elt, attr);
if (attrValue) {
if (attrValue === "this") {
return api.findThisElement(elt, attr);
} else {
return api.querySelectorExt(elt, attrValue);
}
}
} else {
return null;
}

return null;
}

/** @param {Event} evt */
Expand Down
34 changes: 34 additions & 0 deletions test/ext/response-targets.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,38 @@ describe("response-targets extension", function() {
htmx.config.responseTargetPrefersExisting = false;
}
});

describe('status code formatting', function()
{
var attributes = [
"hx-target-404",

"hx-target-40*",
"hx-target-40x",

"hx-target-4*",
"hx-target-4x",
"hx-target-4**",
"hx-target-4xx",

"hx-target-*",
"hx-target-x",
"hx-target-***",
"hx-target-xxx",
];

// String replacement because IE11 doesn't support template literals
var btnMarkup = '<button hx-ext="response-targets" HX_TARGET="#d1" hx-get="/test">Click Me!</button>';
// forEach because IE11 doesn't play nice with closures inside for loops
attributes.forEach(function(attribute) {
it('supports ' + attribute, function() {
this.server.respondWith("GET", "/test", [404, {}, "Not found!"]);
var btn = make(btnMarkup.replace("HX_TARGET", attribute));
var div1 = make('<div id="d1"></div>')
btn.click();
this.server.respond();
div1.innerHTML.should.equal("Not found!");
});
});
});
});
6 changes: 5 additions & 1 deletion www/content/extensions/response-targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title = "response-targets"
+++

This extension allows to specify different target elements to be swapped when
This extension allows you to specify different target elements to be swapped when
different HTTP response codes are received.

It uses attribute names in a form of ``hx-target-[CODE]`` where `[CODE]` is a numeric
Expand Down Expand Up @@ -101,6 +101,10 @@ be looked up (in the given order):
* `hx-target-4*`
* `hx-target-*`.


_If you are using tools that do not support asterisks in HTML attributes, you
may instead use the `x` character, e.g., `hx-target-4xx`._

## Notes

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

0 comments on commit 02f3027

Please sign in to comment.