1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-26 08:39:40 +02:00
Maybe/app/javascript/controllers/auto_submit_form_controller.js
2025-07-23 18:21:37 -04:00

96 lines
2.4 KiB
JavaScript

import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
// By default, auto-submit is "opt-in" to avoid unexpected behavior. Each `auto` target
// will trigger a form submission when the configured event is triggered.
static targets = ["auto"];
static values = {
triggerEvent: { type: String, default: "input" },
};
connect() {
this.autoTargets.forEach((element) => {
const event = this.#getTriggerEvent(element);
element.addEventListener(event, this.handleInput);
});
}
disconnect() {
this.autoTargets.forEach((element) => {
const event = this.#getTriggerEvent(element);
element.removeEventListener(event, this.handleInput);
});
}
handleInput = (event) => {
const target = event.target;
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.element.requestSubmit();
}, this.#debounceTimeout(target));
};
#getTriggerEvent(element) {
// Check if element has explicit trigger event set
if (element.dataset.autosubmitTriggerEvent) {
return element.dataset.autosubmitTriggerEvent;
}
// Check if form has explicit trigger event set
if (this.triggerEventValue !== "input") {
return this.triggerEventValue;
}
// Otherwise, choose trigger event based on element type
const type = element.type || element.tagName;
switch (type.toLowerCase()) {
case "text":
case "email":
case "password":
case "search":
case "tel":
case "url":
case "textarea":
return "blur";
case "number":
case "date":
case "datetime-local":
case "month":
case "time":
case "week":
case "color":
return "change";
case "checkbox":
case "radio":
case "select":
case "select-one":
case "select-multiple":
return "change";
case "range":
return "input";
default:
return "blur";
}
}
#debounceTimeout(element) {
if (element.dataset.autosubmitDebounceTimeout) {
return Number.parseInt(element.dataset.autosubmitDebounceTimeout);
}
const type = element.type || element.tagName;
switch (type.toLowerCase()) {
case "input":
case "textarea":
return 500;
case "select-one":
case "select-multiple":
return 0;
default:
return 500;
}
}
}