mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-23 07:36:22 +00:00
feat: un potencial reemplazo de htmx en stimulus
htmx duplica mucho código y no hace monitoreo de modificaciones en el código sin grandes parches. con esto podemos ir reemplazando htmx por algo que nos resulta más cómodo y eventualmente pasar a turbo.
This commit is contained in:
parent
5b9cd27a79
commit
922fff29ea
1 changed files with 107 additions and 0 deletions
107
app/javascript/controllers/htmx_controller.js
Normal file
107
app/javascript/controllers/htmx_controller.js
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue