UNPKG

oberry

Version:

A lightweight and modern jQuery alternative for DOM manipulation, user interactions, and reactive data binding

568 lines (563 loc) 13.8 kB
// src/core/reactivity/index.ts import { computed, effect, effectScope, signal } from "alien-signals"; var $ref = signal; var $computed = computed; var $effect = effect; var $effectScope = effectScope; // src/core/selector/index.ts function $(selector) { let elements = []; if (typeof selector === "string") { if (selector.includes(" ")) { elements = document.querySelectorAll(selector); } else if (selector.startsWith("#")) { const el = document.getElementById(selector.slice(1)); if (el !== null) { elements = [el]; } } else if (selector.startsWith(".")) { elements = Array.from( document.getElementsByClassName(selector.slice(1)) ); } else if (selector.includes(".") || selector.includes("#")) { elements = document.querySelectorAll(selector); } else { elements = Array.from( document.getElementsByTagName(selector) ); } } else if (selector instanceof HTMLElement) { elements = [selector]; } else if (selector instanceof NodeList || Array.isArray(selector)) { elements = selector; } else { throw new Error("Invalid selector type"); } return new ElementWrapper(elements); } // src/core/wrapper/index.ts var ElementWrapper = class _ElementWrapper { constructor(elements) { if (elements instanceof NodeList) { this.elements = Array.from(elements).filter( (node) => node.nodeType === Node.ELEMENT_NODE ); } else { this.elements = elements; } } class(name, mode) { if (name === void 0) { return Array.from(this.elements[0]?.classList ?? []); } if (mode === void 0 || mode === "toggle") { for (const el of this.elements) { el.classList.toggle(name); } return this; } if (mode === "add") { for (const el of this.elements) { el.classList.add(name); } return this; } if (mode === "remove") { for (const el of this.elements) { el.classList.remove(name); } return this; } return this; } id(id) { if (id === void 0) { const el = this.elements[0]; return el?.id || void 0; } if (this.elements[0]) { this.elements[0].id = id; } return this; } /** * Modify the style of all elements. */ css(styles) { for (const el of this.elements) { Object.assign(el.style, styles); } return this; } html(content) { if (content === void 0) { return this.elements[0]?.innerHTML; } for (const el of this.elements) { el.innerHTML = content; } return this; } text(content) { if (content === void 0) { return this.elements[0]?.innerText; } for (const el of this.elements) { el.innerText = content; } return this; } /** * Get the array of elements. */ getArray() { return Array.from(this.elements); } value(newValue) { const el = this.elements[0]; if (newValue === void 0) { if (!el) { return; } if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) { return el.value; } return; } if (!el) { return this; } if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) { el.value = newValue; } return this; } append(content) { for (const el of this.elements) { if (typeof content === "string") { el.innerHTML += content; } else if (content instanceof HTMLElement) { el.appendChild(content); } else if (content instanceof _ElementWrapper) { for (const child of content.elements) { el.appendChild(child.cloneNode(true)); } } } return this; } prepend(content) { for (const el of this.elements) { if (typeof content === "string") { el.innerHTML = content + el.innerHTML; } else if (content instanceof HTMLElement) { el.insertBefore(content.cloneNode(true), el.firstChild); } else if (content instanceof _ElementWrapper) { content.elements.forEach((childEl, index) => { el.insertBefore(childEl.cloneNode(true), el.children[index] || null); }); } } return this; } after(content) { for (const el of this.elements) { const parent = el.parentNode; if (!parent) { continue; } if (typeof content === "string") { const temp = document.createElement("div"); temp.innerHTML = content; while (temp.firstChild) { parent.insertBefore(temp.firstChild, el.nextSibling); } } else if (content instanceof HTMLElement) { parent.insertBefore(content.cloneNode(true), el.nextSibling); } else if (content instanceof _ElementWrapper) { for (const childEl of content.elements) { parent.insertBefore(childEl.cloneNode(true), el.nextSibling); } } } return this; } before(content) { for (const el of this.elements) { const parent = el.parentNode; if (!parent) { continue; } if (typeof content === "string") { const temp = document.createElement("div"); temp.innerHTML = content; while (temp.firstChild) { parent.insertBefore(temp.firstChild, el); } } else if (content instanceof HTMLElement) { parent.insertBefore(content.cloneNode(true), el); } else if (content instanceof _ElementWrapper) { for (const childEl of content.elements) { parent.insertBefore(childEl.cloneNode(true), el); } } } return this; } /** * Remove all the elements from DOM. */ remove() { for (const el of this.elements) { el.parentNode?.removeChild(el); } this.elements = []; return this; } /** * Find descendants matching the selector within all elements. */ find(selector) { const foundElements = []; for (const el of this.elements) { const found = el.querySelectorAll(selector); foundElements.push( ...Array.from(found).filter( (node) => node.nodeType === Node.ELEMENT_NODE ) ); } return new _ElementWrapper(foundElements); } /** * Find the closest ancestor matching the selector for the first element. */ closest(selector) { const el = this.elements[0]; if (!el) { return null; } const closest = el.closest(selector); if (!closest) { return null; } return new _ElementWrapper([closest]); } /** * Get the parent wrapper of the first element. */ parent() { const el = this.elements[0]; if (!el) { return null; } const parent = el.parentElement; if (!parent) { return null; } return $([parent]); } /** * Get the children wrapper of the first element. */ children() { const el = this.elements[0]; if (!el) { return null; } const children = el.children; if (!children) { return null; } return $(Array.from(children)); } /** * Get the children wrapper of the all elements. */ allChildren() { const children = []; for (const el of this.elements) { children.push(...Array.from(el.children)); } if (!children) { return null; } return $(Array.from(children)); } /** * Bind the value of a ref into the element's inner HTML. */ bindHTML(ref) { $effect(() => { this.html(String(ref())); }); return this; } /** * Bind the value of a ref into the element's text content. */ bind(ref) { $effect(() => { this.text(String(ref())); }); return this; } /** * Bind the input value of the first element into a ref value. */ bindInput(ref) { const el = this.elements[0]; if (!el) { return this; } el.addEventListener("input", () => { ref(el.value); }); return this; } attr(key, value) { if (value === void 0) { const el = this.elements[0]; if (!el) { return null; } return el.getAttribute(key); } for (const el of this.elements) { el.setAttribute(key, value); } return this; } data(key, value) { if (value === void 0) { const el = this.elements[0]; if (!el) { return; } return el.dataset[key]; } for (const el of this.elements) { el.dataset[key] = value; } return this; } on(event, callback) { for (const el of this.elements) { el.addEventListener(event, callback); } return this; } onClick(callback) { return this.on("click", callback); } onMouseOver(callback) { return this.on("mouseover", callback); } onMouseOut(callback) { return this.on("mouseout", callback); } onChange(callback) { return this.on("change", callback); } onInput(callback) { return this.on("input", callback); } onSubmit(callback) { return this.on("submit", callback); } onFocus(callback) { return this.on("focus", callback); } onBlur(callback) { return this.on("blur", callback); } onKeyDown(callback) { return this.on("keydown", callback); } onKeyUp(callback) { return this.on("keyup", callback); } onKeyPress(callback) { return this.on("keypress", callback); } onDblClick(callback) { return this.on("dblclick", callback); } onContextMenu(callback) { return this.on("contextmenu", callback); } onScroll(callback) { return this.on("scroll", callback); } onResize(callback) { return this.on("resize", callback); } onLoad(callback) { return this.on("load", callback); } onDrag(callback) { return this.on("drag", callback); } onDrop(callback) { return this.on("drop", callback); } /** * Get the elements at even positions (1-based indexing). */ even() { const elements = []; for (let i = 0; i < this.elements.length; i++) { if ((i + 1) % 2 === 0 && this.elements[i]) { elements.push(this.elements[i]); } } return new _ElementWrapper(elements); } /** * Get the elements at odd positions (1-based indexing). */ odd() { const elements = []; for (let i = 0; i < this.elements.length; i++) { if ((i + 1) % 2 === 1 && this.elements[i]) { elements.push(this.elements[i]); } } return new _ElementWrapper(elements); } /** * Hide all elements. */ hide() { for (const el of this.elements) { if (!el.dataset.originalDisplay) { const computedStyle = window.getComputedStyle(el); el.dataset.originalDisplay = computedStyle.display; } el.style.display = "none"; } return this; } /** * Show all elements. */ show() { for (const el of this.elements) { const originalDisplay = el.dataset.originalDisplay || ""; el.style.display = originalDisplay === "none" ? "block" : originalDisplay; delete el.dataset.originalDisplay; } return this; } /** * Toggle visibility of all elements. */ toggle() { for (const el of this.elements) { const isVisible = window.getComputedStyle(el).display !== "none"; if (isVisible) { if (!el.dataset.originalDisplay) { el.dataset.originalDisplay = window.getComputedStyle(el).display; } el.style.display = "none"; } else { const originalDisplay = el.dataset.originalDisplay || "block"; el.style.display = originalDisplay; delete el.dataset.originalDisplay; } } return this; } /** * Get the nth element (0-based indexing). */ eq(idx) { const el = this.elements[idx]; return new _ElementWrapper(el ? [el] : []); } /** * Get the first element. */ first() { return this.eq(0); } /** * Get the last element. */ last() { if (this.elements.length === 0) { return new _ElementWrapper([]); } return this.eq(this.elements.length - 1); } /** * Filter elements based on a predicate function or CSS selector. */ filter(predicate) { let filteredElements; if (typeof predicate === "string") { filteredElements = this.elements.filter((el) => el.matches(predicate)); } else { filteredElements = this.elements.filter( (el, index) => predicate(el, index) ); } return new _ElementWrapper(filteredElements); } forEach(callback) { for (const el of this.elements) { callback(new _ElementWrapper([el])); } } length() { return this.elements.length; } isEmpty() { return this.elements.length === 0; } static extend(name, func) { _ElementWrapper.prototype[name] = func; } }; // src/core/creator/index.ts function $new(tag) { const el = document.createElement(tag); const wrapper = new ElementWrapper([el]); return wrapper; } // src/core/plugins/index.ts var Plugin = class { constructor(name, install) { this.name = name; this.install = install; } getInstaller() { return this.install; } }; var installedPlugins = /* @__PURE__ */ new Set(); function use(plugin) { if (installedPlugins.has(plugin.name)) { console.warn(`Plugin "${plugin.name}" is already installed`); return; } try { const extendFunction = (name, func) => { ElementWrapper.extend(name, func); }; plugin.getInstaller()(extendFunction); installedPlugins.add(plugin.name); } catch (error) { console.error(`Failed to install plugin "${plugin.name}":`, error); } } export { $, $computed, $effect, $effectScope, $new, $ref, Plugin, use };