import { check_inv_html_elem, err_msg_finisher } from "./doc-access-extra"; export type Heading_Choice = | "h2" | "h3" | "h4" | "h5" | "h6"; class Detacher { parent: HTMLElement; err_msg: string; constructor(parent: HTMLElement, err_msg: string) { this.parent = parent; this.err_msg = err_msg; } /** Removes parent node, removing its children in the process * * @returns {void} */ detach(): void { check_inv_html_elem(this.parent, this.err_msg); this.parent.remove(); // console.info("Removed parent node"); } } export class Elem extends Detacher { self: Element | HTMLElement | null; tag_name: keyof HTMLElementTagNameMap; parent: HTMLElement; id?: string; /** * * @param {keyof HTMLElementTagNameMap} tag_name * @param {HTMLElement} [parent] - Default: body * @param {string} [id] */ constructor( tag_name: keyof HTMLElementTagNameMap, parent?: HTMLElement, id?: string ) { super( parent || document.body, err_msg_finisher("new creation", parent) ); this.self = null; this.tag_name = tag_name; this.parent = parent ?? document.body; if (id) this.id = id; this.#call(); } #call() { this.self = document.createElement(this.tag_name); this.parent.appendChild(this.self); if (this.id) this.self.id = this.id; } } export class Accessible_Section extends Detacher { self: HTMLElement; heading: HTMLHeadingElement; parent: HTMLElement; heading_choice: Heading_Choice; #heading_text: string; /** Creates an WCAG friendly section with a describer heading of your choice (omitting contrast) * * @typedef {"h2" | "h3" | "h4" | "h5" | "h6"} Heading_Choice * * @param {Heading_Choice} heading_choice * @param {HTMLElement} [parent] - Default: body * @param {string} [heading_text] */ constructor( heading_choice: Heading_Choice, parent?: HTMLElement, heading_text?: string ) { super( parent || document.body, err_msg_finisher("new section", parent) ); this.parent = parent ?? document.body; this.heading_choice = heading_choice; this.self = document.createElement("section"); this.heading = document.createElement( this.heading_choice ); this.#heading_text = heading_text ?? ""; if (heading_text) this.#upd(heading_text); this.attach(); } /** Updates section to keep it accessible * * @returns {void} */ #upd(value: string): void { this.#heading_text = value; this.heading.textContent = this.#heading_text; const heading_text_copy: string = this.heading.textContent .trim() .toLowerCase() .replace(/\s+/g, "") + "-heading"; this.heading.id = heading_text_copy; this.self.setAttribute( "aria-labelledby", this.heading.id ); // console.info("Updated heading text"); } /** Parents both the section and heading * * @returns {void} */ attach(): void { check_inv_html_elem( this.parent, `Can't parent section - invalid parent! Parent: ${parent}` ); this.parent.append(this.self); this.self.appendChild(this.heading); // console.info("Parented new section and heading"); } /** heading's textContent property * */ get heading_text(): string { return this.#heading_text; } /** heading's textContent property * */ set heading_text(value: string) { this.#upd(value); } } export class Tab_Link extends Detacher { self: HTMLAnchorElement; secure: boolean; parent: HTMLElement; accessible: boolean; #link_text: string; /** Creates a link that opens in a new tab when activated * * @param {HTMLElement} [parent] - Default: body * @param {boolean} [secure] - Default: true * @param {boolean} [accessible] - Default: true */ constructor( parent?: HTMLElement, secure?: boolean, accessible?: boolean, link_text?: string ) { super( parent || document.body, err_msg_finisher("new link", parent) ); this.self = document.createElement("a"); this.parent = parent ?? document.body; this.secure = secure ?? true; this.accessible = accessible ?? true; this.#link_text = link_text ?? ""; if (link_text) this.#upd(this.link_text); this.attach(); } /** * * @returns {void} */ #upd(value: string): void { this.#link_text = value; this.self.textContent = this.#link_text; this.self.target = "_blank"; if (this.secure) { this.self.rel = "noopener noreferrer"; } if (this.accessible) { this.self.title = "opens in a new tab"; } } /** Parents the new tab link * * @returns {void} */ attach(): void { check_inv_html_elem( this.parent, `Can't parent new link - invalid parent! Parent: ${this.parent}` ); this.parent.append(this.self); // console.info("Parented new tab link"); } /** heading's textContent property * */ get link_text(): string { return this.#link_text; } /** heading's textContent property * */ set link_text(value: string) { this.#upd(value); } }