type Tags = keyof HTMLElementTagNameMap export default class DOMElement { public item: T public constructor(tagName: Tags | T, options?: ElementCreationOptions) { if (tagName instanceof HTMLElement) { this.item = tagName return } this.item = document.createElement(tagName, options) as any } public static create( tagName: K, options?: ElementCreationOptions ): DOMElement public static create( tagName: string, options?: ElementCreationOptions ): DOMElement { return new DOMElement(tagName as Tags, options) } public static get( query: string | GT, source?: HTMLElement | DOMElement ): DOMElement | undefined { if (!(query instanceof HTMLElement)) { const tmp = (source instanceof DOMElement ? source.item : source || document).querySelector(query) if (!tmp) { return undefined } return new DOMElement(tmp) } return new DOMElement(query) } public on( type: K, listener: (this: T, ev: HTMLElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions ): this public on( type: string, listener: (this: T, ev: Event) => void, options?: boolean | AddEventListenerOptions ): this public on( type: string, listener: (this: T, ev: Event) => void, options?: boolean | AddEventListenerOptions ) { this.item.addEventListener(type, listener, options) return this } public off( type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => void ) { this.item.removeEventListener(type, listener) return this } public text(): string public text(val: string): this public text(val?: string) { if (val) { this.item.innerText = val return this } return this.item.innerText } public html(): string public html(val: string): this public html(val?: string) { if (val) { this.item.innerHTML = val return this } return this.item.innerText } public addClass(...classes: Array) { this.item.classList.add(...classes) return this } public setClass(...classes: Array) { this.item.classList.forEach((cls) => { if (!classes.includes(cls)) { this.item.classList.remove(cls) } }) this.addClass(...classes) return this } public classList(...classes: Array): this public classList(): Array public classList(...classes: Array) { if (!classes) { const res: Array = [] this.item.classList.forEach((el) => res.push(el)) return res } return this.setClass(...classes) } public toggleClass(...classes: Array) { for (const classe of classes) { this.item.classList.toggle(classe) } return this } public removeClass(...classes: Array) { this.item.classList.remove(...classes) return this } public emit(event: E): this public emit(event: string): this public emit(event: string): this { if (event in this.item) { (this.item as any)[event]() return this } this.item.dispatchEvent(new Event(event)) return this } public attr(key: string): string | null public attr(key: string, value: string | null): this public attr(key: keyof T, value: boolean): this public attr(key: string | keyof T, value?: string | boolean | null): this | string | null { if (!value) { return this.item.getAttribute(key as string) } if (value === null) { this.item.removeAttribute(key as string) return this } if (typeof value === 'boolean') { this.item[key as 'draggable'] = value return this } this.item.setAttribute(key as string, value) return this } public data(key: string): string | null public data(key: string, value: string | null): this public data(key: string, value?: string | null): this | string | null { // @ts-ignore return this.attr(`data-${key}`, value) } public style(key: string, value?: string | number) { if (typeof value === 'undefined') { return this.item.style[key as any] } this.item.style[key as any] = value as string return this } public exist() { return !!this.item } public placeBefore(item: DOMElement | HTMLElement) { if (item instanceof DOMElement) { item = item.item } const parent = item.parentElement if (!parent) { throw new Error('can\'t place DOMElement before item because it has no parent') } parent.insertBefore(this.item, item) return this } public placeAsChildOf(item: DOMElement | HTMLElement) { if (item instanceof DOMElement) { item = item.item } item.appendChild(this.item) return this } public place(verb: 'before' | 'asChildOf', item: DOMElement | HTMLElement) { if (verb === 'before') { return this.placeBefore(item) } else { return this.placeAsChildOf(item) } } }