Last active
April 14, 2026 19:17
-
-
Save chzager/aa4d64d486e2568aba03754f64ce1ebe to your computer and use it in GitHub Desktop.
Create new HTML elements
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Creates a new HTML element. | |
| * @author Christoph Zager | |
| * @license CC0-1.0 | |
| * @param {string} definition The tag of the desired HTML element and optionally an ID and CSS classes, in a _query selector_ like notation (i.e. `"div#id.class1.class2"`). | |
| * @param {Array<string | number | HTMLElement | {[key: string]: string | number | boolean | Function}>} content Content (or children) to be created on/in the HTML element. This may be text content, child HTML elements or a record of attributes or event handlers. | |
| * @returns Returns the newly created HTML element with all its content and children. | |
| */ | |
| function makeElement (definition, ...content) | |
| { | |
| const [_m, tagName, _g2, id, _g4, classes] = /^([a-z0-9]+)(#([^.\s\[]+))?(\.(.+))?/.exec(definition); | |
| const element = document.createElement(tagName); | |
| !!id && (element.id = id); | |
| !!classes && element.classList.add(...classes.split(".")); | |
| for (let item of content.filter(i => (i !== null) && (i !== undefined))) | |
| { | |
| switch (typeof item) | |
| { | |
| case "bigint": | |
| case "boolean": | |
| case "number": | |
| element.appendChild(document.createTextNode(item.toString())); | |
| break; | |
| case "string": | |
| for (const [match, unicodeChar] of item.matchAll(/&#x([0-9a-f]+);/ig)) | |
| { | |
| item = item.replace(match, JSON.parse(`"\\u${unicodeChar}"`)); | |
| } | |
| element.appendChild(document.createTextNode(item)); | |
| break; | |
| case "object": | |
| if (item instanceof HTMLElement) | |
| { | |
| element.appendChild(item); | |
| } | |
| else if (!Array.isArray(item)) | |
| { | |
| for (const [key, value] of Object.entries(item)) | |
| { | |
| if (key.startsWith("data-")) | |
| { | |
| element.dataset[key.substring(5)] = value.toString(); | |
| } | |
| else if (typeof value === "string") | |
| { | |
| element.setAttribute(key, value); | |
| } | |
| else | |
| { | |
| // @ts-expect-error "implicit any". | |
| element[key] = value; | |
| } | |
| } | |
| } | |
| else | |
| { | |
| throw new TypeError(`Expected String, Number, Object or HTMLElement, got ${item.constructor.name ?? typeof item}`); | |
| } | |
| break; | |
| } | |
| } | |
| return element; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment