/** * Shortcut for querySelector. * @template {HTMLElement} T * @returns {T} */ const q = s => document.querySelector(s); /** * Shortcut for querySelectorAll. * @template {HTMLElement} T * @returns {T[]} */ const qa = s => document.querySelectorAll(s); /** * An easier, chainable, object-oriented way to create and update elements * and children according to related data. Subclass ElemJS to create useful, * advanced data managers, or just use it inline to quickly make a custom element. * Created by Cadence Ember in 2018. */ class ElemJS { constructor(type) { if (type instanceof HTMLElement) { // If passed an existing element, bind to it this.bind(type); } else { // Otherwise, create a new detached element to bind to this.bind(document.createElement(type)); } this.children = []; } /** Bind this construct to an existing element on the page. */ bind(element) { this.element = element; this.element.js = this; return this; } /** Add a class. */ class() { for (let name of arguments) if (name) this.element.classList.add(name); return this; } /** Remove a class. */ removeClass() { for (let name of arguments) if (name) this.element.classList.remove(name); return this; } /** Set a JS property on the element. */ direct(name, value) { if (name) this.element[name] = value; return this; } /** Set an attribute on the element. */ attribute(name, value) { if (name) this.element.setAttribute(name, value != undefined ? value : ""); return this; } /** Set a style on the element. */ style(name, value) { if (name) this.element.style[name] = value; return this; } /** Set the element's ID. */ id(name) { if (name) this.element.id = name; return this; } /** Attach a callback function to an event on the element. */ on(name, callback) { this.element.addEventListener(name, callback); return this; } /** Set the element's text. */ text(name) { this.element.innerText = name; return this; } /** Create a text node and add it to the element. */ addText(name) { const node = document.createTextNode(name); this.element.appendChild(node); return this; } /** Set the element's HTML content. */ html(name) { this.element.innerHTML = name; return this; } /** * Add children to the element. * Children can either be an instance of ElemJS, in * which case the element will be appended as a child, * or a string, in which case the string will be added as a text node. * Each child should be a parameter to this method. */ child(...children) { for (const toAdd of children) { if (typeof toAdd === "object" && toAdd !== null) { // Should be an instance of ElemJS, so append as child toAdd.parent = this; this.element.appendChild(toAdd.element); this.children.push(toAdd); } else if (typeof toAdd === "string") { // Is a string, so add as text node this.addText(toAdd); } } return this; } childAt(index, toAdd) { if (typeof toAdd === "object" && toAdd !== null) { toAdd.parent = this; this.children.splice(index, 0, toAdd); if (index >= this.element.childNodes.length) { this.element.appendChild(toAdd.element) } else { this.element.childNodes[index].insertAdjacentElement("beforebegin", toAdd.element) } } } /** * Remove all children from the element. */ clearChildren() { this.children.length = 0; while (this.element.lastChild) this.element.removeChild(this.element.lastChild); } /** * Remove this element. */ remove() { let index; if (this.parent && (index = this.parent.children.indexOf(this)) !== -1) { this.parent.children.splice(index, 1); } this.parent = null; this.element.remove(); } } /** Shortcut for `new ElemJS`. */ function ejs(tag) { return new ElemJS(tag); } export {q, qa, ElemJS, ejs}