template/src/main/js/Validation.ts

191 lines
5.3 KiB
TypeScript

import {$, $a, doAfterLoad, getMetaProperty} from "./Template";
/**
* Removes all validation-related information from `form`.
*
* @param form the form to hide validation information from
*/
export function clearFormValidity(form: HTMLFormElement): void {
clearMessageStatus(form);
$a("input", form).forEach((input: Element) => {
if (!(input instanceof HTMLInputElement)) return;
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
*/
export function showMessageType(card: HTMLElement | HTMLFormElement,
message?: string,
type?: "error" | "info" | "success" | "warning"): void {
if (card instanceof HTMLFormElement)
card = $(`article[data-status-for="${card.id}"]`)!;
const output = $("output", card)!;
card.classList.remove("hidden", "error", "info", "success", "warning");
if (message == null || type == null) {
card.classList.add("hidden");
output.innerText = "";
} else {
card.classList.add(type);
output.innerText = message;
}
}
/**
* Removes the message in `card`, hiding it in the process.
*
* @param card the card to clear the message from
*/
export 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`
*/
export 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`
*/
export 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`
*/
export 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`
*/
export function showMessageWarning(card: HTMLElement, message: string): void {
showMessageType(card, message, "warning");
}
/**
* Marks `input` as neither valid nor invalid.
*
* @param input
*/
export 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
*/
export 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
*/
export 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: Element) => {
if (!(close instanceof HTMLElement)) return;
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"] ?? "";
});
});