jessquery
Version:
Modern JavaScript is pretty good, but typing document.querySelector() is a pain. This is a tiny library that makes DOM manipulation easy. jQuery is around 80kb (30kb gzipped), while this is only around 8kb (3.5kb gzipped). Lots of JSDoc comments so it's s
125 lines (104 loc) • 2.99 kB
JavaScript
import { errorHandler, giveContext } from "./errors.js"
import { addMethods } from "./methods.js"
import { getDOMElement } from "./DOM.js"
export function $(selector, fixed = false) {
return createProxy("$", selector, fixed)
}
export function $$(selector, fixed = false) {
return createProxy("$$", selector, fixed)
}
function createProxy(type, selector, fixed = false) {
const elements = getDOMElement(selector, {
all: type === "$$",
sanitize: false,
})
if (!elements[0]) {
return errorHandler(new Error(`No elements.`), giveContext(type, selector))
}
return addMethods(selector, elements, fixed)
}
export function createQueue() {
const mainQueue = []
const deferredQueue = []
let isRunning = false
async function runQueue() {
if (isRunning) return
isRunning = true
while (mainQueue.length > 0) {
const fn = mainQueue.shift()
await fn()
}
if (deferredQueue.length > 0 && mainQueue.length === 0) {
while (deferredQueue.length > 0) {
const { fn, args } = deferredQueue.shift()
await eachArgument(fn, args)
}
}
isRunning = false
}
function addToQueue(fn) {
mainQueue.push(fn)
runQueue()
}
function defer(fn, args = []) {
deferredQueue.push({ fn, args })
if (!isRunning) {
runQueue()
}
}
return {
addToQueue,
defer,
}
}
export function queueAndReturn(addToQueue, getProxy) {
return function queueFunction(fn, context, eager = true) {
return (...args) => {
addToQueue(async () => {
try {
await eachArgument(fn, args, eager)
} catch (error) {
errorHandler(error, context)
}
})
return getProxy()
}
}
}
export function handlerMaker(elements, customMethods) {
return {
get(_, prop) {
if (elements.length && elements.length === 1) {
elements = elements[0]
}
if (prop === "raw") {
return elements
}
if (prop in customMethods) {
return customMethods[prop]
}
if (Array.isArray(elements) && typeof elements[prop] === "function") {
return function (...args) {
const result = elements[prop](...args)
return result instanceof Array
? addMethods(elements[prop].name + args, result)
: addMethods(elements[prop].name + args, [result])
}
}
return typeof elements[prop] === "function"
? elements[prop].bind(elements)
: elements[prop]
},
}
}
async function eachArgument(fn, args, eager = true) {
const isThenable = (value) => value && typeof value.then === "function"
const resolvedArgs = []
for (const arg of args) {
resolvedArgs.push(isThenable(arg) && eager ? await arg : arg)
}
const result = fn(...resolvedArgs)
if (isThenable(result)) {
await result
}
}