/* * This file is part of NoccyLabs JavaScript Standard Library (JSL) * Copyright (c) 2025, NoccyLabs. Licensed under GNU GPL v2 or later * * */ /** * A helper class to create (and manipulate) elements in the DOM. * */ class DomHelper { /** * Create a new element without all the fuzz. * * @param {string} tag The name of the HTML tag * @param {object} attr Map of attributes to apply to the element * @param {array|Element|string} children Children or single child/text to apply * @returns Element */ createEl(tag, attr = {}, children = []) { //console.debug(`create: ${tag}`, attr, children); let el = document.createElement(tag); this.apply(el, attr); this.append(el, children); return el; }; /** * Apply attributes from an object to an element * * @param {Element} tag The element to modify * @param {object} attr Key-value pairs of attributes to apply, or if null remove */ apply(tag, attr) { Object.keys(attr).forEach(key => { if (key.match(/^on:/)) { const ev = key.substring(3); tag.addEventListener(ev, attr[key]); return; } if (attr[key] === null) { tag.removeAttribute(key); } else { tag.setAttribute(key, attr[key]); } }); } /** * Append one or more children or text nodes to an element. * * @param {Element} tag The element to modify * @param {array|Element|string} children List of elements or single element to append to the element * @returns */ append(tag, children) { //console.debug(`append: ${tag.nodeName}`, children); if (typeof children == 'object' && children instanceof Element) { //console.debug(`-> appended element`); tag.appendChild(children); return; } if (typeof children == 'string') { //console.debug(`-> appended string`); let n = document.createTextNode(children); tag.appendChild(n); return; } if (Array.isArray(children)) { children.forEach(child => { this.append(tag, child); }); //console.debug(`-> appended nested`); } } /** * Apply templated values to a string * * @param {string} str The string to perform interpolation on * @param {object} tpl A string of key-value pair to replace between percent signs * @returns string */ interpolate(str, tpl) { Object.keys(tpl).forEach(key => { str = str.replace(`%${key}%`, tpl[key]); }); return str; } }; // The DOM helper const dom = new DomHelper(); // Proxy for creating any supported HTML element via el.TAG const el = new Proxy(dom, { get(target,name) { return name in target ? target[name] : (attr = {}, children = []) => target.createEl(name, attr, children); } }); export { dom, el };