/** * fluent-dom-esm v1.1.0 * * Fluent DOM Manipulation, adapted to ESM and cranked up to v1.1(.0). * * https://git.itsericwoodward.com/eric/fluent-dom-esm * * v1.1.0 Copyright (c) 2025 Eric Woodward * Original copyright (c) 2009 Tommy Montgomery (https://glacius.tmont.com/articles/fluent-dom-manipulation-in-javascript) * * Released under the WTFPL (Do What the Fuck You Want to Public License) * * @author Eric Woodward (v1.1.0 update) * @author Tommy Montgomery (original) * @license http://sam.zoy.org/wtfpl/ */ import type { FluentDomObject } from "./fluent-dom-esm.types"; import { version } from "../package.json" with { type: "json" }; import { isFluentDomObject, isHTMLElement, isNumber, isString, } from "./fluent-dom-esm.type-guards"; /** * IIFE that creates the FluentDomObject as default export */ export default (function () { /** * Wraps provided element in a FluentDomObject which is then returned */ const FluentDom = function (node: HTMLElement) { return new (FluentDomInternal as any)(node); }; /** * Creates a new HTML element which is wrapped in a FluentDomObject and returned */ FluentDom.create = FluentDom.c = function (tagName: string) { const f = new (FluentDomInternal as any)(); f.create(tagName); return f; }; /** * The internal representation of the FluentDomObject */ const FluentDomInternal = function ( this: FluentDomObject, node?: HTMLElement, ) { let root = node || null; // adds several new features this.fluentDom = version; /** * Gets or sets the named attribute on the wrapped HTMLElement */ this.a = this.attr = function (name, value) { if (!root || (value && !root.setAttribute)) { throw new Error("Cannot set an attribute on a non-element"); } if (!value) return root.getAttribute(name); root.setAttribute(name, value); return this; }; /** * Appends value to wrapped HTMLElement */ this.app = this.append = function (value) { if (!root || !root?.appendChild) { throw new Error("Cannot append to a non-element"); } const type = typeof value; if (type === "object") { if (isFluentDomObject(value)) { const domVal = value.toDom(); if (domVal !== null) root.appendChild(domVal); } else if (isHTMLElement(value)) { root.appendChild(value); } else { throw new Error( "Invalid argument: not an HTMLElement or FluentDom object", ); } } else if (isNumber(value) || isString(value)) { root.appendChild(document.createTextNode(`${value}`)); } else { throw new Error( `Invalid argument: not a valid type (${typeof value})`, ); } return this; }; /** * Creates a new wrapped HTMLElement of the indicated tag */ this.c = this.create = function (tagName) { root = document.createElement(tagName); return this; }; /** * Gets or sets the "class" attribute on the wrapped HTMLElement */ this.className = this.cls = function (value) { return this.attr("class", value); }; /** * Sets the wrapped HTMLElement to null */ this.clear = function () { root = null; return this; }; /** * Gets or sets the "href" attribute on the wrapped HTMLElement */ this.h = this.href = function (link) { return this.attr("href", link); }; /** * Gets or sets the wrapped HTMLElement's "innerHTML" property */ this.html = function (content) { if (!root) { throw new Error( "Cannot get or set innerHTML for a non-element", ); } if (!content) return root.innerHTML; root.innerHTML = content; return this; }; /** * Gets or sets the "id" attribute on the wrapped HTMLElement */ this.id = function (value) { return this.attr("id", value); }; /** * Passes props to the "addEventListener" function on the wrapped HTMLElement */ this.l = this.listen = function (...props) { if (!root || !root.addEventListener) { throw new Error("Cannot addEventListener to a non-element"); } root.addEventListener(...props); return this; }; /** * Gets or sets the wrapped HTMLElement's "outerHTML" property */ this.ohtml = function (content) { if (!root) { throw new Error( "Cannot get or set outerHTML for a non-element", ); } if (!content) return root.outerHTML; root.outerHTML = content; return this; }; /** * Gets or sets a one or more style attributes on the wrapped HTMLElement */ this.s = this.style = function (prop, value) { if (!root) { throw new Error("Cannot get or set style for a non-element"); } if (typeof prop === "undefined") return root.style; if (typeof value !== "undefined") { root.style[prop as any] = value; return this; } if (typeof prop === "string") return root.style[prop as any]; if (typeof prop !== "object") { throw new Error( `Invalid argument: "prop" must be string or object (found ${typeof prop})`, ); } Object.keys(prop).forEach((key) => { (root as HTMLElement).style[key as any] = prop[key as any]; }); return this; }; /** * Gets or sets the wrapped HTMLElement's "innerText" property */ this.t = this.text = function (text) { if (!root) { throw new Error( "Cannot get or set innerText for a non-element", ); } if (typeof text === "undefined") return root.innerText; return this.append(text); }; /** * Gets or sets the "title" attribute on the wrapped HTMLElement */ this.title = function (value) { if (!root) { throw new Error( "Cannot get or set outerHTML for a non-element", ); } return this.attr("title", value); }; /** * Gets the wrapped HTMLElement itself */ this.toDom = function () { return root; }; /** * Passes props to the "removeEventListener" function on the wrapped HTMLElement */ this.unlisten = function (...props) { if (!root || !root.removeEventListener) { throw new Error("Cannot removeEventListener on a non-element"); } root.removeEventListener(...props); return this; }; }; return FluentDom; })() as unknown as FluentDomObject;