add support for querySeletor add toHTMLElement clean up comments fix bug in README
156 lines
4.8 KiB
JavaScript
156 lines
4.8 KiB
JavaScript
// @license magnet:?xt=urn:btih:723febf9f6185544f57f0660a41489c7d6b4931b&dn=wtfpl.txt
|
|
const isFluentDomObject = (value) => !!value.fluentDom;
|
|
const isHTMLElement = (value) => !!value.nodeType;
|
|
const isNumber = (value) => typeof value === "number";
|
|
const isString = (value) => typeof value === "string";
|
|
/**
|
|
* fluent-dom-esm v2.1.0
|
|
*
|
|
* Fluent DOM Manipulation, adapted to ESM and cranked up to v2.1(.0).
|
|
*
|
|
* https://git.itsericwoodward.com/eric/fluent-dom-esm
|
|
*
|
|
* v2.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 (v2.1.0 update)
|
|
* @author Tommy Montgomery (original)
|
|
* @license http://sam.zoy.org/wtfpl/
|
|
*/
|
|
const APP_VERSION = "2.1.0";
|
|
const fluentDomEsm = (function() {
|
|
const FluentDom = function(nodeOrQuerySelector) {
|
|
if (typeof nodeOrQuerySelector !== "string")
|
|
return new FluentDomInternal(nodeOrQuerySelector);
|
|
const f = new FluentDomInternal();
|
|
f.querySelector(nodeOrQuerySelector);
|
|
return f;
|
|
};
|
|
FluentDom.create = FluentDom.c = function(tagName) {
|
|
const f = new FluentDomInternal();
|
|
f.create(tagName);
|
|
return f;
|
|
};
|
|
const FluentDomInternal = function(node) {
|
|
let root = node || null;
|
|
this.fluentDom = APP_VERSION;
|
|
this.a = this.attr = function(name, value) {
|
|
if (!root || typeof name === "undefined" || typeof value === "undefined") {
|
|
throw new Error("Cannot set an attribute on a non-element");
|
|
}
|
|
root.setAttribute(name, value);
|
|
return this;
|
|
};
|
|
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;
|
|
};
|
|
this.c = this.create = function(tagName) {
|
|
root = document.createElement(tagName);
|
|
return this;
|
|
};
|
|
this.className = this.cls = function(value) {
|
|
return this.attr("class", value);
|
|
};
|
|
this.clear = function() {
|
|
root = null;
|
|
return this;
|
|
};
|
|
this.h = this.href = function(url) {
|
|
return this.attr("href", url);
|
|
};
|
|
this.html = function(content) {
|
|
if (!root) {
|
|
throw new Error(
|
|
"Cannot get or set innerHTML for a non-element"
|
|
);
|
|
}
|
|
root.innerHTML = content;
|
|
return this;
|
|
};
|
|
this.id = function(value) {
|
|
return this.attr("id", value);
|
|
};
|
|
this.l = this.listen = function(...props) {
|
|
if (!root || !root.addEventListener) {
|
|
throw new Error("Cannot addEventListener to a non-element");
|
|
}
|
|
root.addEventListener(...props);
|
|
return this;
|
|
};
|
|
this.q = this.querySelector = function(selector) {
|
|
root = document.querySelector(selector);
|
|
return this;
|
|
};
|
|
function styleFunction(prop, value) {
|
|
if (!root) {
|
|
throw new Error("Cannot get or set style for a non-element");
|
|
}
|
|
if (typeof prop === "string" && typeof value !== "undefined") {
|
|
root.style[prop] = value;
|
|
return this;
|
|
}
|
|
if (typeof prop !== "object") {
|
|
throw new Error(
|
|
`Invalid argument: "prop" must be string or object (found ${typeof prop})`
|
|
);
|
|
}
|
|
Object.keys(prop).forEach((key) => {
|
|
root.style[key] = prop[key];
|
|
});
|
|
return this;
|
|
}
|
|
this.s = this.style = styleFunction;
|
|
this.t = this.text = function(text) {
|
|
if (!root) {
|
|
throw new Error("Cannot set innerText for a non-element");
|
|
}
|
|
return this.append(text);
|
|
};
|
|
this.title = function(title) {
|
|
if (!root) {
|
|
throw new Error("Cannot get or set title for a non-element");
|
|
}
|
|
return this.attr("title", title);
|
|
};
|
|
this.toDom = this.toHTMLElement = function() {
|
|
return root;
|
|
};
|
|
this.unlisten = function(...props) {
|
|
if (!root || !root.removeEventListener) {
|
|
throw new Error("Cannot removeEventListener on a non-element");
|
|
}
|
|
root.removeEventListener(...props);
|
|
return this;
|
|
};
|
|
};
|
|
return FluentDom;
|
|
})();
|
|
export {
|
|
fluentDomEsm as default
|
|
};
|
|
// @license-end
|