Skip to content

Repository files navigation

fQuery

CI npm version npm downloads minzipped size license

Lightweight JavaScript library for DOM querying, traversal, manipulation, events, animation, AJAX, and browser utilities.

Highlights

  • Default ESM export for browser projects, bundlers, and DOM-enabled Node environments
  • Browser UMD bundle in dist/ exposed as globalThis.fQuery and globalThis.$
  • Familiar, chainable QuerySet API alongside equivalent static functions
  • Querying across elements, documents, fragments, shadow roots, collections, and multiple contexts
  • DOM traversal, manipulation, attributes, styles, events, selection, and form helpers
  • Promise-like AJAX requests and animations, with animation queues and built-in effects
  • Dynamic script and stylesheet loading, sanitization, cookies, and browser utilities
  • @fr0st/core helpers exposed with an _ prefix
  • JSDoc-powered IntelliSense

Installation

Browser projects and bundlers

npm i @fr0st/query

fQuery is an ES module. In a browser environment, importing it initializes the current window and document, assigns window.$, and returns the query function.

import $ from '@fr0st/query';

$('.card').addClass('is-ready');

Browser (UMD)

Load the bundle from your own copy or a CDN:

<script src="/path/to/dist/fquery.min.js"></script>
<!-- or -->
<script src="https://cdn.jsdelivr.net/npm/@fr0st/query@latest/dist/fquery.min.js"></script>
<script>
    $('.card').addClass('is-ready');
</script>

The UMD bundle exposes the same object as both globalThis.fQuery and globalThis.$. If another library already uses $, restore it while continuing to use fQuery:

fQuery.noConflict();
fQuery('.card').addClass('is-ready');

Node and DOM implementations

Outside a browser, the default export is an initializer. Pass it a Window, such as one created by JSDOM:

import { JSDOM } from 'jsdom';
import register from '@fr0st/query';

const { window } = new JSDOM('<main><p class="message">Hello</p></main>');
const $ = register(window);

$('.message').setText('Hello from fQuery');

The DOM implementation is supplied by the application and is not a dependency of fQuery.

Quick Start

Query existing nodes and chain operations:

const cards = $('.card')
    .addClass('is-ready')
    .setAttribute('aria-busy', 'false');

cards.find('.title').setText('Ready');

cards.addEvent('click.cards', (event) => {
    $(event.currentTarget).toggleClass('is-active');
});

Create nodes from HTML and insert them into the document:

const notice = $('<aside class="notice">Saved</aside>');

notice
    .appendTo(document.body)
    .fadeIn({ duration: 200 });

Run code when the document is ready:

$(() => {
    $('[data-autofocus]').focus();
});

Query Model

$(selector, context?) and $.query(selector, context?) return a QuerySet. $.queryOne(selector, context?) returns a QuerySet containing at most one node.

A selector can be:

  • a CSS selector string;
  • an HTML string beginning with <;
  • a Node, DocumentFragment, ShadowRoot, Document, or Window;
  • a NodeList, HTMLCollection, QuerySet, or array of nodes; or
  • for $() only, a callback to run when the document is ready.

The optional context can be a selector or one or more element, fragment, shadow-root, or document contexts. It defaults to the configured document.

const formFields = $('input, select', '#account-form');
const firstError = $.queryOne('.error', formFields);

console.log(formFields.length);
console.log(firstError.get(0));

QuerySet

A QuerySet is iterable and keeps an ordered collection of nodes. Traversal and filtering methods return new sets; DOM mutation methods are chainable and generally return the current set.

  • new $.QuerySet(nodes?): construct a set directly.
  • query.length: return the number of nodes.
  • query.get(index?): return one node, including negative indexes, or all nodes when no index is given.
  • query.each(callback): run a callback for each node and return the current set.
  • query.map(callback): map the nodes into a new QuerySet.
  • query.slice(begin?, end?): return a sliced QuerySet.
  • query.add(selector, context?): add nodes and return a new sorted, deduplicated set.
  • query.eq(index): return the node at an index as a new set.
  • query.first() / query.last(): return the first or last node as a new set.
  • query[Symbol.iterator](): iterate over the contained nodes.

DOM API

Most operations are available in two forms:

$.addClass(selector, 'active');
$(selector).addClass('active');

Unless an entry shows full signatures, the static form takes the target selector as its first argument and the QuerySet form omits that argument. A nodeFilter can be a CSS selector, node, node collection, QuerySet, array, or callback.

Finding

  • $.find(selector, context?) / query.find(selector): find all matching descendants.
  • $.findOne(selector, context?) / query.findOne(selector): find the first matching descendant.
  • $.findByClass(className, context?) / query.findByClass(className): find descendants by class.
  • $.findOneByClass(className, context?) / query.findOneByClass(className): find the first descendant by class.
  • $.findById(id, context?) / query.findById(id): find descendants by ID.
  • $.findOneById(id, context?) / query.findOneById(id): find the first descendant by ID.
  • $.findByTag(tagName, context?) / query.findByTag(tagName): find descendants by tag name.
  • $.findOneByTag(tagName, context?) / query.findOneByTag(tagName): find the first descendant by tag name.

Traversal

  • child(nodeFilter?): return the first matching child.
  • children(nodeFilter?, { elementsOnly? }): return matching children.
  • contents(): return children including text and comment nodes.
  • closest(nodeFilter?, limitFilter?): return the closest matching ancestor.
  • parent(nodeFilter?): return matching direct parents.
  • parents(nodeFilter?, limitFilter?): return matching ancestors up to an optional limit.
  • next(nodeFilter?) / prev(nodeFilter?): return the next or previous matching sibling.
  • nextAll(nodeFilter?, limitFilter?) / prevAll(nodeFilter?, limitFilter?): return following or preceding matching siblings.
  • siblings(nodeFilter?, { elementsOnly? }): return matching siblings.
  • commonAncestor(): return the common ancestor of all nodes.
  • offsetParent(): return the first node's positioned offset parent.
  • fragment(): return the first node's DocumentFragment.
  • shadow(): return the first node's ShadowRoot.

The static forms of children, nextAll, parents, and prevAll also accept { first }; their singular QuerySet counterparts provide the first-result behavior.

Filtering

Filtering methods return matching nodes; their is... and has... counterparts return booleans.

  • filter(nodeFilter) / filterOne(nodeFilter): nodes matching a filter.
  • not(nodeFilter) / notOne(nodeFilter): nodes not matching a filter.
  • connected() / isConnected(): connection to the configured document.
  • equal(otherSelector) / isEqual(otherSelector, { shallow? }): DOM equality.
  • same(otherSelector) / isSame(otherSelector): node identity.
  • fixed() / isFixed(): fixed positioning on a node or ancestor.
  • hidden() / visible(): visibility filters.
  • isHidden() / isVisible(): visibility tests.
  • is(nodeFilter): whether any node matches a filter.
  • withAnimation() / hasAnimation(): active fQuery animations.
  • withAttribute(attribute) / hasAttribute(attribute): attribute presence.
  • withChildren() / hasChildren(): child-node presence.
  • withClass(...classes) / hasClass(...classes): class presence.
  • withCSSAnimation() / hasCSSAnimation(): computed CSS animations.
  • withCSSTransition() / hasCSSTransition(): computed CSS transitions.
  • withData(key?) / hasData(key?): fQuery custom data.
  • hasDataset(key): dataset presence.
  • withDescendent(nodeFilter) / hasDescendent(nodeFilter): matching descendants.
  • withProperty(property) / hasProperty(property): property presence.
  • hasFragment() / hasShadow(): fragment or shadow-root presence.

Attributes and content

Getter methods read the first matching node. Setter and removal methods apply to each matching node.

  • getAttribute(attribute) / setAttribute(attribute, value) / removeAttribute(attribute): attributes.
  • getProperty(property) / setProperty(property, value) / removeProperty(property): JavaScript properties.
  • getDataset(key) / setDataset(key, value) / removeDataset(key): serialized dataset values.
  • getHTML() / setHTML(html): HTML content.
  • getText() / setText(text): text content.
  • getValue() / setValue(value): form-control values.

Custom data

Custom data is stored separately from DOM attributes and dataset.

  • getData(key?): read one value or the full data object from the first node.
  • setData(key, value): set a custom value on every node.
  • removeData(key?): remove one value or all custom data.
  • cloneData(otherSelector): copy custom data to other nodes.

Classes and styles

  • addClass(...classes) / removeClass(...classes) / toggleClass(...classes): change classes. Arrays and space-separated strings are accepted.
  • css(style): read one or more computed CSS values from the first node.
  • getStyle(style): read inline style values from the first node.
  • setStyle(style, value, { important? }): set one or more inline styles.
  • removeStyle(style): remove an inline style.
  • hide() / show() / toggle(): change element visibility.

Size, position, and scrolling

height() and width() accept { boxSize, outer }. Use $.CONTENT_BOX, $.PADDING_BOX, $.BORDER_BOX, $.MARGIN_BOX, or $.SCROLL_BOX for boxSize.

  • height(options?) / width(options?): read the first node's computed dimensions.
  • center({ offset? }): return center coordinates.
  • position({ offset? }): return positioned coordinates.
  • rect({ offset? }): return the bounding rectangle.
  • constrain(containerSelector): keep nodes within a container.
  • distTo(x, y, { offset? }) / distToNode(otherSelector): calculate distances.
  • nearestTo(x, y, { offset? }) / nearestToNode(otherSelector): return the nearest node.
  • percentX(x, { offset?, clamp? }) / percentY(y, { offset?, clamp? }): convert a coordinate to a percentage of the node.
  • getScrollX() / getScrollY(): read scroll coordinates.
  • setScroll(x, y) / setScrollX(x) / setScrollY(y): set scroll coordinates.

Manipulation

Methods accepting otherSelector also accept nodes, collections, QuerySets, arrays, and—where creation is supported—HTML strings.

  • append(otherSelector) / prepend(otherSelector): insert content inside each target.
  • appendTo(otherSelector) / prependTo(otherSelector): insert each target inside another node.
  • before(otherSelector) / after(otherSelector): insert content adjacent to each target.
  • insertBefore(otherSelector) / insertAfter(otherSelector): insert each target adjacent to another node.
  • replaceWith(otherSelector) / replaceAll(otherSelector): replace targets or other nodes.
  • wrap(otherSelector) / wrapAll(otherSelector) / wrapInner(otherSelector): wrap nodes or their contents.
  • unwrap(nodeFilter?): remove matching parents while preserving their contents.
  • clone({ deep?, events?, data?, animations? }): clone nodes and optionally their fQuery state.
  • detach(): remove nodes while preserving associated state.
  • remove(): remove nodes and their associated state.
  • empty(): remove all child nodes and their associated state.
  • attachShadow({ open? }): attach a shadow root to the first node.

Create nodes without a target:

  • $.create(tagName?, options?): create an element with optional html, text, class, style, value, attributes, properties, and dataset.
  • $.createComment(comment): create a comment node.
  • $.createText(text): create a text node.
  • $.createFragment(): create a document fragment.
  • $.createRange(): create a range.

Events

Event names may include namespaces such as click.menu. Returning false from an event callback prevents the default action.

  • addEvent(events, callback, options?): add one or more event handlers.
  • addEventOnce(events, callback, options?): add self-removing handlers.
  • addEventDelegate(events, delegate, callback, options?): add delegated handlers.
  • addEventDelegateOnce(events, delegate, callback, options?): add self-removing delegated handlers.
  • removeEvent(events?, callback?, options?): remove matching handlers.
  • removeEventDelegate(events?, delegate?, callback?, options?): remove matching delegated handlers.
  • cloneEvents(otherSelector): copy registered handlers to other nodes.
  • triggerEvent(events, options?): trigger events on every node.
  • triggerOne(event, options?): trigger an event on the first node.
  • blur() / click() / focus(): invoke the native action on the first node.

Listener options include capture and passive; the static $.addEvent() form also accepts delegate and selfDestruct. Trigger options include data, detail, bubbles, and cancelable.

$.mouseDragFactory(down, move?, up?, options?) creates a mouse/touch drag callback. Options include debounce, passive, preventDefault, and the required number of touches.

Animation and Queues

Animation

await $.fadeIn('.panel', { duration: 200 });

$('.meter').animate((node, progress) => {
    node.style.width = `${progress * 100}%`;
}, { duration: 500 });

Common animation options are:

Option Default Description
duration 1000 Duration in milliseconds.
type 'ease-in-out' One of linear, ease-in, ease-out, or ease-in-out.
infinite false Repeat indefinitely.
debug false Expose timing values through dataset.
queueName 'default' Queue used by QuerySet animation methods.
  • animate(callback, options?): run a custom progress callback.
  • dropIn(options?) / dropOut(options?): drop nodes from or toward a direction.
  • fadeIn(options?) / fadeOut(options?): animate opacity.
  • rotateIn(options?) / rotateOut(options?): animate a 3D rotation.
  • slideIn(options?) / slideOut(options?): slide nodes from or toward a direction.
  • squeezeIn(options?) / squeezeOut(options?): animate dimensions from or toward a direction.
  • stop({ finish? }): stop active animations, finishing them by default.

Built-in effects restore the inline styles they change when they complete or are stopped with finish: true. Stopping with finish: false leaves the current animated styles in place.

The static forms return an AnimationSet. QuerySet forms queue the work and return the current set.

new $.Animation(node, callback, options?) creates one promise-like animation. It supports then, catch, finally, clone(node), stop({ finish? }), and update(time?). new $.AnimationSet(animations) combines animations and supports then, catch, finally, and stop({ finish? }).

Use $.getAnimationDefaults() and $.setAnimationDefaults(options) to inspect or change defaults. $.useTimeout(true) selects the timer fallback instead of animation frames.

Queues

$('.notice')
    .fadeIn({ duration: 150 })
    .delay(500)
    .fadeOut({ duration: 150 });
  • $.queue(selector, callback, { queueName? }) and query.queue(callback, { queueName? }) queue callbacks.
  • $.clearQueue(selector, { queueName? }) and query.clearQueue({ queueName? }) clear the default or named queue. Pass { queueName: null } to clear all queues.
  • query.delay(duration, { queueName? }) queues a delay.

AJAX

fQuery uses XMLHttpRequest and returns a promise-like AjaxRequest:

const request = $.get('/api/items', { page: 2 }, {
    responseType: 'json',
});

const { response, xhr } = await request;
  • $.ajax(options?): create a request with explicit options.
  • $.get(url, data?, options?): send a GET request.
  • $.post(url, data?, options?): send a POST request.
  • $.put(url, data?, options?): send a PUT request.
  • $.patch(url, data?, options?): send a PATCH request.
  • $.delete(url, options?): send a DELETE request.

Request options include:

Option Default Description
url Current location Request URL.
method 'GET' HTTP method.
data null String, array, object, boolean, or FormData payload.
contentType 'application/x-www-form-urlencoded' Request content type, or false to omit it.
responseType / mimeType null Expected response type or MIME override.
username / password HTTP authentication values.
timeout 0 Timeout in milliseconds.
cache true Add a cache-busting query value when disabled.
processData true Encode object data according to contentType.
isLocal Auto-detected Treat the request as local.
rejectOnCancel true Reject when cancel() is called.
headers {} Additional request headers.
beforeSend / afterSend null Hooks receiving the XMLHttpRequest.
onProgress / onUploadProgress null Hooks receiving (progress, xhr, event).

AjaxRequest exposes its xhr, implements then, catch, and finally, and can be cancelled with request.cancel(reason?). Use $.getAjaxDefaults() and $.setAjaxDefaults(options) to inspect or change request defaults.

$.parseParams(data) produces URL-encoded parameters and $.parseFormData(data) produces a FormData object.

Scripts, Stylesheets, and Cookies

  • $.loadScript(url, attributes?, options?): load one script. Scripts default to ordered execution.
  • $.loadScripts(urls, options?): load multiple scripts. Entries can be URLs or attribute objects.
  • $.loadStyle(url, attributes?, options?): load one stylesheet.
  • $.loadStyles(urls, options?): load multiple stylesheets. Entries can be URLs or attribute objects.

Loader options include cache and an alternate document context. Each function returns a Promise.

Cookie helpers are $.getCookie(name), $.setCookie(name, value, { expires?, path?, secure? }), and $.removeCookie(name, { path?, secure? }). Cookie expiration is specified in seconds.

Parsing, Selection, and Utilities

Parsing and sanitization

  • $.parseHTML(html): parse HTML into an array of elements; top-level text and comment nodes are discarded.
  • $.parseDocument(input, { contentType? }): parse text into a Document.
  • $.sanitize(html, allowedTags?): remove disallowed elements and attributes from HTML.

The sanitizer's allowedTags argument maps lowercase tag names to arrays of allowed attribute names or regular expressions. String rules match exact attribute names, while the '*' entry applies attributes to every allowed tag. URI attributes using the javascript: protocol are removed; other protocols are not filtered.

Selection

  • select() / selectAll(): select the first node or all target nodes.
  • beforeSelection() / afterSelection(): insert nodes before or after the current selection.
  • wrapSelection(): wrap the current selection with the target nodes.

Static-only helpers are $.getSelection() and $.extractSelection().

Forms and general utilities

  • serialize(): serialize successful form controls into a query string.
  • serializeArray(): serialize successful form controls into { name, value } entries.
  • index(): return the first node's index within its parent.
  • indexOf(nodeFilter?): return the first matching index within the set.
  • normalize(): join adjacent text nodes and remove empty text nodes.
  • sort(): sort nodes by document position.
  • tagName(): return the first node's lowercase tag name.

Additional static utilities are:

  • $.debounce(callback) to allow one callback execution per microtask;
  • $.exec(command, value?) to call document.execCommand();
  • $.ready(callback) to run after DOM readiness; and
  • $.noConflict() to restore the previous global $.

Configuration and FrostCore

The active DOM environment can be inspected with $.getWindow() and $.getContext(), or changed with $.setWindow(window) and $.setContext(document). Registering fQuery configures both automatically.

Every export from @fr0st/core is exposed with an underscore prefix:

const id = $._randomString(12);
const values = $._unique([1, 1, 2]);

These prefixed helpers follow the installed FrostCore version. Consult FrostCore for its complete API.

Behavior Notes

  • Selector-based operations use the configured document unless an explicit context is supplied.
  • QuerySet getter methods generally inspect the first node; mutations generally apply to every node.
  • queryOne() and findOne...() QuerySet methods return sets containing zero or one node.
  • HTML strings are recognized by query and creation-aware manipulation APIs when the trimmed string begins with <.
  • Custom data, registered events, queues, and animations are tracked outside the DOM and can be cloned or cleaned up by fQuery manipulation methods.
  • Event namespaces affect fQuery handler registration and removal; native event dispatch still uses the underlying event name.
  • Ajax uses XMLHttpRequest, not fetch.
  • fQuery requires a browser DOM or a compatible DOM implementation.

Development

fQuery supports Node.js ^20.19.0, ^22.13.0, or >=24.

npm ci
npm test
npm run js-lint
npm run build
npm pack --dry-run

CI runs the Playwright suite in Chromium, Firefox, and WebKit, tests supported Node.js release lines, rebuilds the UMD bundles, verifies that dist/ is current, and validates the package contents.

License

fQuery is released under the MIT License.

About

Lightweight JavaScript library for DOM querying, traversal, manipulation, events, animation, AJAX, and browser utilities.

Topics

Resources

Stars

4 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages