UNPKG

deleight

Version:

A library with 9 modules for writing more expressive web applications with traditional HTML, CSS and JavaScript.

245 lines (244 loc) 6.17 kB
"use strict"; /** * This module should provide a richer API for making elements look more like * simple objects in JavaScript code. It should supercede the Selectors module * once it has been properly tested. The main benefit is these objects improve * composability with other aspects of deleight so we can write less code. * * Using this library we can do things like: * * `assign(wrap(element), { href: './item/link', first: { section: {textContent: 'First section text'} } })` * * more straightforwardly. Combining with Aliad module will also enable us to * shorten long names like `textContent`. * * @module */ Object.defineProperty(exports, "__esModule", { value: true }); exports.selectAll = exports.selectFirst = exports.All = exports.First = exports.Attrs = exports.unwrap = exports.wrap = exports.$$ = exports.$ = exports.Selector = void 0; const own_js_1 = require("../../object/member/own/own.js"); class SelectorObject { #proxy; constructor(element) { this.element = element; } get(p) { } ; set(p, value) { return true; } ; delete(p) { return true; } ; get proxy() { if (!this.#proxy) this.#proxy = new Proxy(this, handler); return this.#proxy; } get [exports.$$]() { return this.element; } } /** * A selector that holds all the other EOM objects as properties and also behaves like a `list` of * the children wlements of the wrapped element. * * @example * */ class Selector extends SelectorObject { #attrs; #first; #all; get attrs() { if (!this.#attrs) this.#attrs = new (this.constructor.Attrs)(this.element).proxy; return this.#attrs; } get first() { if (!this.#first) this.#first = new (this.constructor.First)(this.element).proxy; return this.#first; } get all() { if (!this.#all) this.#all = new (this.constructor.All)(this.element).proxy; return this.#all; } } exports.Selector = Selector; exports.$ = Symbol(); exports.$$ = Symbol(); /** * Wraps a regular element with an instance of ELOMElement * * @example * * * @param element * @returns */ function wrap(element) { return new Selector(element).proxy; } exports.wrap = wrap; /** * Returns the element wrapped by any instance of SelectorObject. * * @example * * * @param selectorObject * @returns */ function unwrap(selectorObject) { return selectorObject[exports.$$]; } exports.unwrap = unwrap; const handler = { get(target, p) { if (p === exports.$$) return target.element; if (p === exports.$) return target; if (target instanceof Selector && Reflect.has(target, p)) { let result = target[p]; if (result instanceof Function) result = result.bind(target); return result; } return target.get(p); }, set(target, p, value) { return target.set(p, value); }, deleteProperty(target, p) { return target.delete(p); }, ownKeys(target) { if (target instanceof Selector) { const result = []; const len = target.element.children.length; for (let i = 0; i < len; i++) result.push(`${i}`); return result; } else return Reflect.ownKeys(target); } }; /** * A selector object that effectively holds all element attributes as properties. * * @example * */ class Attrs extends SelectorObject { get(p) { return this.element.getAttribute(p); } set(p, value) { this.element.setAttribute(p, value); return true; } ; delete(p) { this.element.removeAttribute(p); return true; } } exports.Attrs = Attrs; /** * A selector object that effectively holds the first objects that match specified queries as properties. * * @example * */ class First extends SelectorObject { static { this.selector = selectFirst; } get(p) { const element = this.constructor.selector(this.element, p); if (element) return new Selector(element); } set(p, ...values) { const element = this.constructor.selector(this.element, p); if (element) element.replaceWith(...values); return true; } ; delete(p) { const element = this.constructor.selector(this.element, p); if (element) element.remove(); return true; } } exports.First = First; /** * Wrapper to ensure we keep returning Selector element instances. */ const arrayHandler = { get(target, p) { p = (0, own_js_1.realKey)(p); if (typeof p === "number") { return new Selector(target[p]); } return target[p]; } }; /** * A selector object that effectively holds all objects that match specified queries as properties. * * @example * */ class All extends SelectorObject { static { this.selector = selectAll; } get(p) { const elements = this.constructor.selector(this.element, p); if (elements) return new Proxy(Array.from(elements), arrayHandler); } set(p, ...values) { const elements = this.constructor.selector(this.element, p) || []; let i = 0; for (let element of elements) element.replaceWith(values[i++]); return true; } ; delete(p) { const elements = this.constructor.selector(this.element, p) || []; for (let element of elements) element.remove(); return true; } } exports.All = All; /** * The same as `element.querySelector` * * @param element * @param selector * @returns */ function selectFirst(element, selector) { return element.querySelector(selector); } exports.selectFirst = selectFirst; /** * The same as `element.querySelectorAll` * * @param element * @param selector * @returns */ function selectAll(element, selector) { return element.querySelectorAll(selector); } exports.selectAll = selectAll;