197 lines
5.6 KiB
TypeScript
197 lines
5.6 KiB
TypeScript
if ((window as any).fwdekker == null) throw new Error("Validation module requires main module.");
|
|
const {$, $a, doAfterLoad, getMetaProperty} = (window as any).fwdekker;
|
|
|
|
|
|
/**
|
|
* Removes all validation-related information from `form`.
|
|
*
|
|
* @param form the form to hide validation information from
|
|
*/
|
|
function clearFormValidity(form: HTMLFormElement): void {
|
|
clearMessageStatus(form);
|
|
$a("input", form).forEach((input: HTMLInputElement) => clearInputValidity(input));
|
|
}
|
|
|
|
|
|
/**
|
|
* Shows a `type` message in `card`.
|
|
*
|
|
* @param card the card to show `message` in, or `form` to show the `message` in the form's status card
|
|
* @param message the message to show in `card`, or `undefined` if `card` should be hidden
|
|
* @param type the type of message to show in `card`, or `undefined` if `card` should be hidden
|
|
*/
|
|
function showMessageType(card: HTMLElement | HTMLFormElement,
|
|
message?: string,
|
|
type?: "error" | "info" | "success" | "warning"): void {
|
|
if (card instanceof HTMLFormElement) {
|
|
card = $(`article[data-status-for="${card.id}"]`);
|
|
if (card == null) throw new Error("Could not find status card.");
|
|
}
|
|
|
|
card.classList.remove("hidden", "error", "info", "success", "warning");
|
|
|
|
if (message == null || type == null) {
|
|
card.classList.add("hidden");
|
|
$("output", card).innerText = "";
|
|
} else {
|
|
card.classList.add(type);
|
|
$("output", card).innerText = message;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes the message in `card`, hiding it in the process.
|
|
*
|
|
* @param card the card to clear the message from
|
|
*/
|
|
function clearMessageStatus(card: HTMLElement): void {
|
|
showMessageType(card);
|
|
}
|
|
|
|
/**
|
|
* Shows an error message in `card`.
|
|
*
|
|
* @param card the card to show `message` in
|
|
* @param message the error message to show in `card`
|
|
*/
|
|
function showMessageError(card: HTMLElement, message: string): void {
|
|
showMessageType(card, message, "error");
|
|
}
|
|
|
|
/**
|
|
* Shows an information message in `card`.
|
|
*
|
|
* @param card the card to show `message` in
|
|
* @param message the message to show in `card`
|
|
*/
|
|
function showMessageInfo(card: HTMLElement, message: string): void {
|
|
showMessageType(card, message, "info");
|
|
}
|
|
|
|
/**
|
|
* Shows a success message in `card`.
|
|
*
|
|
* @param card the card to show `message` in
|
|
* @param message the success message to show in `card`
|
|
*/
|
|
function showMessageSuccess(card: HTMLElement, message: string): void {
|
|
showMessageType(card, message, "success");
|
|
}
|
|
|
|
/**
|
|
* Shows a warning message in `card`.
|
|
*
|
|
* @param card the card to show `message` in
|
|
* @param message the success message to show in `card`
|
|
*/
|
|
function showMessageWarning(card: HTMLElement, message: string): void {
|
|
showMessageType(card, message, "warning");
|
|
}
|
|
|
|
|
|
/**
|
|
* Marks `input` as neither valid nor invalid.
|
|
*
|
|
* @param input
|
|
*/
|
|
function clearInputValidity(input: HTMLInputElement): void {
|
|
input.classList.remove("valid", "invalid");
|
|
input.removeAttribute("aria-invalid");
|
|
input.removeAttribute("aria-errormessage");
|
|
|
|
const label = $(`label[for="${input.id}"]`);
|
|
if (label != null)
|
|
label.classList.remove("valid", "invalid");
|
|
|
|
const hint = $(`*[data-hint-for="${input.id}"]`);
|
|
if (hint != null) {
|
|
hint.classList.remove("valid", "invalid");
|
|
|
|
hint.role = null;
|
|
hint.innerText = hint.dataset["hint"] ?? "";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shows to the user that `input` is invalid.
|
|
*
|
|
* @param input the input to show as invalid
|
|
* @param message the message explaining what is invalid
|
|
*/
|
|
function showInputInvalid(input: HTMLInputElement, message?: string): void {
|
|
clearInputValidity(input);
|
|
|
|
input.classList.add("invalid");
|
|
input.setAttribute("aria-invalid", "true");
|
|
input.focus();
|
|
|
|
const label = $(`label[for="${input.id}"]`);
|
|
if (label != null)
|
|
label.classList.add("invalid");
|
|
|
|
const hint = $(`*[data-hint-for="${input.id}"]`);
|
|
if (hint != null && message != null) {
|
|
hint.classList.add("invalid");
|
|
|
|
input.setAttribute("aria-errormessage", hint.id);
|
|
hint.role = "alert";
|
|
hint.innerText = message;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shows to the user that `input` is valid.
|
|
*
|
|
* @param input the input to show as valid
|
|
* @param message the message to show at the input
|
|
*/
|
|
function showInputValid(input: HTMLInputElement, message?: string): void {
|
|
clearInputValidity(input);
|
|
|
|
input.classList.add("valid");
|
|
input.setAttribute("aria-invalid", "false");
|
|
|
|
const label = $(`label[for="${input.id}"]`);
|
|
if (label != null)
|
|
label.classList.add("valid");
|
|
|
|
const hint = $(`*[data-hint-for="${input.id}"]`);
|
|
if (hint != null) {
|
|
hint.classList.add("valid");
|
|
|
|
if (message != null) hint.innerText = message;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* If the `fwd:validation:load-hints` meta property has been set, loads hints and implements close buttons for forms.
|
|
*/
|
|
doAfterLoad(() => {
|
|
if (getMetaProperty("fwd:validation:load-forms") === undefined) return;
|
|
|
|
$a(".status-card .close").forEach((close: HTMLElement) => {
|
|
close.addEventListener("click", (event: MouseEvent) => {
|
|
event.preventDefault();
|
|
|
|
close.parentElement!.classList.add("hidden");
|
|
});
|
|
});
|
|
|
|
$a("input + small[data-hint]").forEach((hint: Element) => {
|
|
if (!(hint instanceof HTMLElement)) return;
|
|
|
|
hint.innerText = hint.dataset["hint"] ?? "";
|
|
});
|
|
});
|
|
|
|
|
|
// Export to `window`
|
|
(window as any).fwdekker = (window as any).fwdekker ?? {};
|
|
(window as any).fwdekker.validation = {
|
|
clearFormValidity,
|
|
clearMessageStatus, showMessageError, showMessageInfo, showMessageSuccess, showMessageWarning,
|
|
clearInputValidity, showInputInvalid, showInputValid
|
|
};
|
|
export {};
|