102 lines
2.7 KiB
JavaScript
102 lines
2.7 KiB
JavaScript
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);
|