smol htmx

This commit is contained in:
Daniel Bulant 2026-03-14 20:56:16 +01:00
parent b3625489d1
commit 9e9514db8c
No known key found for this signature in database
2 changed files with 103 additions and 0 deletions

102
a5/static/htmlx-smol.js Normal file
View file

@ -0,0 +1,102 @@
const elementTimers = new Map;
function addTimer(element, timerId) {
const timers = elementTimers.get(element) || [];
timers.push(timerId)
elementTimers.set(element, timers);
}
function removeTimerElement(element) {
const timers = elementTimers.get(element) || [];
for (const timer of timers) {
clearInterval(timer);
}
elementTimers.delete(element);
}
/**
*
* @param {Event} event
*/
function handleEvent(e) {
e.preventDefault();
handleTrigger(e.target);
}
/**
* @param {String} duration
*/
function parseDuration(duration) {
const parsed = duration.match(/(\d+(?:\.\d+)?(s|ms))/);
if (!parsed) throw new Error("Unknown duration");
const num = parseFloat(parsed[1]);
const type = parsed[2];
const length = { "s": 1000, "ms": 1 };
return num * length[type];
}
/**
* @param {Element|Document} element
*/
function registerHandlers(element) {
const elements = element.querySelectorAll("[hx-get],[hx-trigger],[hx-target]");
for (const element of elements) {
const trigger = element.getAttribute("hx-trigger");
if (trigger) {
const [key, duration, ...rest] = trigger.split(" ");
if (rest.length) throw new Error("Unknown trigger: " + rest);
const parsedDuration = parseDuration(duration);
if (key !== "every") throw new Error("Unknown trigger: " + key);
addTimer(element, setInterval(handleTrigger.bind(null, element), parsedDuration));
} else {
if ("onclick" in element) {
element.onclick = handleEvent;
}
}
}
}
/**
* @param {Element} element
*/
async function handleTrigger(element) {
const replaceUrl = element.getAttribute("hx-replace-url");
const get = element.getAttribute("hx-get");
const targetSelector = element.getAttribute("hx-target");
const targetElement = document.querySelector(targetSelector) || element;
if (replaceUrl && replaceUrl !== "false") {
const targetUrl = replaceUrl == "true" ? get : replaceUrl;
if (targetUrl) {
window.history.replaceState({}, "", targetUrl);
}
}
if (get) {
const res = await fetch(get, {
headers: {
"HX-Request": "true",
"HX-Trigger": element.id,
"HX-Target": targetSelector,
"HX-Current-URL": document.location.href
}
});
const data = await res.text();
if (!targetElement) {
console.error("Target element not found! Attempted:", targetSelector);
return;
}
const elements = [targetElement, ...targetElement.querySelectorAll("*")];
for (const element of elements) {
removeTimerElement(element);
}
targetElement.innerHTML = data;
registerHandlers(targetElement);
}
}
window.onload = () => registerHandlers(document);

View file

@ -24,6 +24,7 @@
rel="stylesheet"
>
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js" integrity="sha384-/TgkGk7p307TH7EXJDuUlgG3Ce1UVolAOFopFekQkkXihi5u/6OCvVKyz1W+idaz" crossorigin="anonymous"></script>
{#<script src="/static/htmlx-smol.js"></script>#}
</head>
<body>
<div class="bg-gradient"></div>