personal_website/frontend/elementcreate.tsx
2024-08-01 14:36:35 +02:00

71 lines
1.8 KiB
TypeScript

/// <reference path="./utils/element-types.d.ts" />
/// <reference path="./utils/events.d.ts" />
/// <reference path="./utils/intrinsic-elements.d.ts" />
export interface Children {
children?: AttributeValue;
}
export interface CustomElementHandler {
(attributes: Attributes, contents: (string | HTMLElement)[]): HTMLElement;
}
export interface Attributes {
[key: string]: AttributeValue;
}
export function createElement(
tag: string | CustomElementHandler,
attrs: Attributes & Children | undefined = {},
...children: (string | HTMLElement)[]
): HTMLElement {
if (typeof tag === "function") {
if (attrs == null) {
attrs = { num: 0 };
}
if (children == null) {
children = [""];
}
return tag(attrs, children);
}
const retElement = document.createElement(tag);
for (let name in attrs) {
if (name && attrs.hasOwnProperty(name)) {
let value = attrs[name];
if (typeof value === "number") {
retElement.setAttribute(name, value.toString());
} else if (typeof value === "function") {
retElement.addEventListener(name.slice(2), value);
}
else {
retElement.setAttribute(name, value);
}
}
}
for (let i = 2; i < arguments.length; i++) {
let child = arguments[i];
// check if child is a HTMLElement
if (child.nodeType != undefined) {
retElement.appendChild(child);
continue;
}
if (child instanceof Array) {
for (let j = 0; j < child.length; j++) {
if (child[j].nodeType != undefined) retElement.appendChild(child[j]);
else retElement.appendChild(document.createTextNode(child[j].toString()));
}
continue;
}
// child is a string
retElement.appendChild(document.createTextNode(child.toString()));
}
return retElement;
}