diff --git a/html/static/js/elemjs/.gitrepo b/html/static/js/elemjs/.gitrepo
new file mode 100644
index 0000000..655daa8
--- /dev/null
+++ b/html/static/js/elemjs/.gitrepo
@@ -0,0 +1,12 @@
+; DO NOT EDIT (unless you know what you are doing)
+;
+; This subdirectory is a git "subrepo", and this file is maintained by the
+; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
+;
+[subrepo]
+ remote = /home/cloud/Code/pinski-plugins/elemjs
+ branch = other
+ commit = 637cc076fac2f1060257a47002d8196ac96f078c
+ parent = 00bba69a743d3dc0bf4b1cbfb27fffdb28d634f8
+ method = merge
+ cmdver = 0.4.0
diff --git a/html/static/js/elemjs/elemjs.mjs b/html/static/js/elemjs/elemjs.mjs
new file mode 100644
index 0000000..563d921
--- /dev/null
+++ b/html/static/js/elemjs/elemjs.mjs
@@ -0,0 +1,78 @@
+/** @returns {HTMLElement} */
+export function q(s) {
+ return document.querySelector(s)
+}
+
+export class ElemJS {
+ constructor(type) {
+ if (type instanceof HTMLElement) this.bind(type)
+ else this.bind(document.createElement(type))
+ this.children = [];
+ }
+ bind(element) {
+ /** @type {HTMLElement} */
+ this.element = element
+ // @ts-ignore
+ this.element.js = this
+ return this
+ }
+ class() {
+ for (let name of arguments) if (name) this.element.classList.add(name);
+ return this;
+ }
+ removeClass() {
+ for (let name of arguments) if (name) this.element.classList.remove(name);
+ return this;
+ }
+ direct(name, value) {
+ if (name) this.element[name] = value;
+ return this;
+ }
+ attribute(name, value) {
+ if (name) this.element.setAttribute(name, value);
+ return this;
+ }
+ style(name, value) {
+ if (name) this.element.style[name] = value;
+ return this;
+ }
+ id(name) {
+ if (name) this.element.id = name;
+ return this;
+ }
+ text(name) {
+ this.element.innerText = name;
+ return this;
+ }
+ addText(name) {
+ const node = document.createTextNode(name)
+ this.element.appendChild(node)
+ return this
+ }
+ html(name) {
+ this.element.innerHTML = name;
+ return this;
+ }
+ event(name, callback) {
+ this.element.addEventListener(name, event => callback(event))
+ }
+ child(toAdd, position) {
+ if (typeof(toAdd) == "object") {
+ toAdd.parent = this;
+ if (typeof(position) == "number" && position >= 0) {
+ this.element.insertBefore(toAdd.element, this.element.children[position]);
+ this.children.splice(position, 0, toAdd);
+ } else {
+ this.element.appendChild(toAdd.element);
+ this.children.push(toAdd);
+ }
+ } else if (typeof toAdd === "string") {
+ this.text(toAdd)
+ }
+ return this;
+ }
+ clearChildren() {
+ this.children.length = 0;
+ while (this.element.lastChild) this.element.removeChild(this.element.lastChild);
+ }
+}