diff --git a/makeDOM.ts b/makeDOM.ts index b80bfe9..0668784 100644 --- a/makeDOM.ts +++ b/makeDOM.ts @@ -2,68 +2,79 @@ // Licensed under AGPL-3.0, check `LICENSE` for the full text. type ElementProperties = { - [key in keyof HTMLElementTagNameMap[T]]: HTMLElementTagNameMap[T][key]; + [key in keyof HTMLElementTagNameMap[T]]: + | HTMLElementTagNameMap[T][key] + | string; } & { - [key in keyof HTMLElementEventMap as `@${key}`]: ( - this: HTMLElement, - ev: HTMLElementEventMap[key] - ) => void; + [key in keyof HTMLElementEventMap as `@${key}`]: ( + this: HTMLElement, + ev: HTMLElementEventMap[key], + ) => void; }; type DOMElem = Node | string; type WithClassOrId = - | `${T}#${string}` - | `${T}.${string}`; + | `${T}#${string}` + | `${T}.${string}`; export function $el( - name: T | WithClassOrId, - ...desc: [Partial>, ...DOMElem[]] | DOMElem[] + name: T | WithClassOrId, + ...desc: [Partial>, ...DOMElem[]] | DOMElem[] ): HTMLElementTagNameMap[T] { - // Take off ID or class from the name - let elementName = name as string; - let className = ""; - let id = ""; + // Take off ID or class from the name + let elementName = name as string; + let className = ""; + let id = ""; - if (name.includes("#")) { - [elementName, id] = name.split("#"); - } + if (name.includes("#")) { + [elementName, id] = name.split("#"); + } - if (name.includes(".")) { - [elementName, className] = name.split("."); - } + if (name.includes(".")) { + [elementName, className] = name.split("."); + } - // Create the element and add the attributes (if found) - const el = document.createElement(elementName as T); - if (className) { - el.className = className; - } - if (id) { - el.id = id; - } + // Create the element and add the attributes (if found) + const el = document.createElement(elementName as T); + if (className) { + el.className = className; + } + if (id) { + el.id = id; + } - const attributes = desc[0]; - if (typeof attributes === "object" && !(attributes instanceof Node)) { - for (const attr in attributes) { - const value = (attributes as Record)[attr]; - if (attr.startsWith("@")) { - el.addEventListener(attr.substring(1), value); - } else if (attr === "dataset") { - for (const key in value) { - el.dataset[key] = value[key]; - } - } else { - el[attr as keyof HTMLElementTagNameMap[T]] = value; - } - } - desc.shift(); - } + const attributes = desc[0]; + if (typeof attributes === "object" && !(attributes instanceof Node)) { + for (const attr in attributes) { + const value = (attributes as Record)[attr]; + if (attr.startsWith("@")) { + el.addEventListener( + attr.substring(1), + value as EventListenerOrEventListenerObject, + ); + } else if (attr === "dataset") { + for (const key in value as Record) { + el.dataset[key] = (value as Record)[key]; + } + } else { + // For some tricky attributes, set them the old fashioned way using strings + if (typeof value === "string") { + el.setAttribute(attr, value as string); + } else { + el[attr as keyof HTMLElementTagNameMap[T]] = + value as HTMLElementTagNameMap[T][keyof HTMLElementTagNameMap[T]]; + } + } + } + desc.shift(); + } - for (const item of desc as DOMElem[]) { - el.appendChild(item instanceof Node ? item : document.createTextNode(item)); - } + for (const item of desc as DOMElem[]) { + el.appendChild(item instanceof Node ? item : document.createTextNode(item)); + } - return el; + return el; } export default $el;