mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-23 00:46:23 +00:00
108 lines
2.6 KiB
JavaScript
108 lines
2.6 KiB
JavaScript
|
import { Controller } from "stimulus";
|
||
|
|
||
|
/*
|
||
|
* Un controlador que imita a HTMX
|
||
|
*/
|
||
|
export default class extends Controller {
|
||
|
connect() {
|
||
|
// @todo Convertir en <template>
|
||
|
this.placeholder = "<span class=\"placeholder w-100\" aria-hidden=\"true\"></span>";
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Obtiene la URL y elimina la acción.
|
||
|
*
|
||
|
* @param event [Event]
|
||
|
*/
|
||
|
getUrlOnce(event) {
|
||
|
this.getUrl(event);
|
||
|
|
||
|
event.target.dataset.action = event.target.dataset.action.replace("htmx#getUrlOnce", "").trim();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Lanza el evento que va a descargar la URL y agregarse en algún
|
||
|
* lado.
|
||
|
*
|
||
|
* @param event [Event]
|
||
|
*/
|
||
|
getUrl(event) {
|
||
|
// @todo Stimulus >1
|
||
|
const value = event.target.dataset.htmxGetUrlParam;
|
||
|
|
||
|
if (value) {
|
||
|
window.dispatchEvent(new CustomEvent("htmx:getUrl", { detail: { value } }));
|
||
|
} else {
|
||
|
console.error("Missing data-htmx-get-url-param attribute on element", event.target);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Realiza una petición.
|
||
|
*
|
||
|
* @param url [String]
|
||
|
* @return [Promise<Response>]
|
||
|
*/
|
||
|
async request(url) {
|
||
|
const headers = new Headers();
|
||
|
const signal = window.abortController?.signal;
|
||
|
|
||
|
headers.set("HX-Request", "true");
|
||
|
|
||
|
return fetch(url, { headers, signal });
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Obtiene la URL enviada por el evento y reemplaza el contenido del
|
||
|
* elemento.
|
||
|
*/
|
||
|
async swap(event) {
|
||
|
const response = await this.request(event.detail.value);
|
||
|
|
||
|
if (response.ok) {
|
||
|
this.element.innerHTML = this.placeholder;
|
||
|
this.element.innerHTML = await response.text();
|
||
|
this.triggerEvents(response.headers);
|
||
|
window.htmx.process(this.element);
|
||
|
} else {
|
||
|
console.error(response);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Agrega el resultado de la descarga al final del elemento.
|
||
|
*/
|
||
|
async beforeend(event) {
|
||
|
const response = await this.request(event.detail.value);
|
||
|
|
||
|
if (response.ok) {
|
||
|
this.element.insertAdjacentHTML("beforeend", this.placeholder);
|
||
|
this.element.lastElementChild.outerHTML = await response.text();
|
||
|
|
||
|
this.triggerEvents(response.headers);
|
||
|
|
||
|
// @todo Asume que cada endpoint solo devuelve un elemento por vez
|
||
|
window.htmx.process(this.element.lastElementChild);
|
||
|
} else {
|
||
|
console.error(response);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Lanza los eventos que vienen con la respuesta.
|
||
|
*/
|
||
|
triggerEvents(headers) {
|
||
|
if (!headers.has("HX-Trigger")) return;
|
||
|
|
||
|
const events = JSON.parse(headers.get("HX-Trigger"));
|
||
|
|
||
|
setTimeout(() => {
|
||
|
for (const event in events) {
|
||
|
const detail = events[event];
|
||
|
|
||
|
window.dispatchEvent(new CustomEvent(event, { detail }));
|
||
|
}
|
||
|
}, 1);
|
||
|
}
|
||
|
}
|