mirror of
				https://git.sr.ht/~cadence/cloudtube
				synced 2025-10-28 20:19:13 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			138 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * 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.
 | |
|  */
 | |
| class ElemJS {
 | |
| 	constructor(type) {
 | |
| 		if (type instanceof HTMLElement) {
 | |
| 			// If passed an existing element, bind to it
 | |
| 			this.bind(type);
 | |
| 		} else if (typeof type === "string") {
 | |
| 			// Otherwise, create a new detached element to bind to
 | |
| 			this.bind(document.createElement(type));
 | |
| 		} else {
 | |
| 			throw new Error("Cannot create an element of type ${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);
 | |
| 		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;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Remove all children from the element.
 | |
| 	 */
 | |
| 	clearChildren() {
 | |
| 		this.children.length = 0;
 | |
| 		while (this.element.lastChild) this.element.removeChild(this.element.lastChild);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /** Shortcut for `new ElemJS`. */
 | |
| function ejs(tag) {
 | |
| 	return new ElemJS(tag);
 | |
| }
 | |
| 
 | |
| export {q, qa, ElemJS, ejs};
 | 
