Documentation

The complete jsKjs 1.0.0 API — every function, directive, and option, with examples. Also available as a compact AI-GUIDE.md for pasting into AI coding assistants.

Core & Selectors

Everything starts with $(). A jsKjs set is a real Array subclass, so native methods (map, spread, for...of) work alongside the chainable API.

$()

$(selector [, context]) · $(element) · $(html) · $(fn)

The heart of the library. Accepts a CSS selector (optionally scoped to a context), a DOM node, window, a NodeList/array, an HTML string (creates elements), or a function (runs on DOM ready).

$('.card')                    // CSS selector
$('li', '#menu')              // scoped to context
$(document.body)              // wrap a node
$('<div class="x">Hi</div>')  // create elements
$(() => console.log('DOM ready'));

.each()

.each((index, element) => {}) → self

Iterate the set jQuery-style. Inside the callback, this is the current element.

$('.item').each(function (i, el) {
  console.log(i, el.id, this === el); // true
});

.get()

.get([index]) → element | element[]

Without arguments returns a plain array of all elements; with an index returns that raw element (negative indexes count from the end). Bracket access $(x)[0] also works.

$('.item').get();    // [el, el, el]
$('.item').get(-1);  // last raw element

.eq()

.eq(index) → KJ

Reduce the set to the element at the given index, returned as a new chainable set. Negative indexes count from the end.

$('.item').eq(1).addClass('second');
$('.item').eq(-1).text('last');

.first() / .last()

.first() → KJ · .last() → KJ

Shortcuts for .eq(0) and .eq(-1).

$('li').first().addClass('head');
$('li').last().addClass('tail');

.index()

.index([element]) → number

Without arguments, the position of the first element among its siblings. With an element, its position within this set.

$('.active').index();  // e.g. 2

.add()

.add(selector | elements) → KJ

Merge more elements into the set (deduplicated).

$('.card').add('.banner').addClass('highlight');
Content

Read and write element content and form values.

.html()

.html([value]) → string | self

Get the first element’s innerHTML, or set it on every element in the set.

$('#box').html();               // read
$('#box').html('<b>New</b>');   // write

.text()

.text([value]) → string | self

Get or set textContent. Setting always escapes — it can never inject HTML.

$('#title').text('Safe & sound');

.val()

.val([value]) → any | self

Get or set form values. Checkboxes read/write booleans; multi-selects read as arrays.

$('#email').val();          // 'a@b.c'
$('#agree').val(true);      // checks the box
$('#tags').val();           // ['js', 'css'] for multi-select
Attributes & Data

HTML attributes, DOM properties, and per-element data storage (backed by a WeakMap, so removed elements are garbage-collected automatically).

.attr()

.attr(name [, value]) · .attr(object) → string | self

Get an attribute from the first element, or set one or many on all elements.

$('img').attr('src');
$('img').attr('alt', 'Logo');
$('a').attr({ href: '/', title: 'Home' });

.removeAttr()

.removeAttr(name) → self

Remove an attribute from every element in the set.

$('input').removeAttr('disabled');

.prop()

.prop(name [, value]) → any | self

Get or set a DOM property (as opposed to an HTML attribute) — checked, disabled, selectedIndex, etc.

$('#opt-in').prop('checked');       // true/false
$('button').prop('disabled', true);

.data()

.data([key [, value]]) · .data(object) → any | self

Read data-* attributes (JSON auto-parsed) or store arbitrary values against elements. Stored values live in a WeakMap — no memory leaks, no cleanup.

<div id="u" data-config='{"admin":true}'></div>

$('#u').data('config').admin;       // true (parsed)
$('#u').data('profile', { id: 7 }); // store anything
$('#u').data();                     // all data merged

.removeData()

.removeData(key) → self

Delete a stored data value.

$('#u').removeData('profile');
Classes

Space-separated multi-class strings are supported everywhere.

.addClass()

.addClass(names) → self

Add one or more classes.

$('.card').addClass('active highlight');

.removeClass()

.removeClass([names]) → self

Remove classes; with no argument, removes all classes.

$('.card').removeClass('active');
$('.card').removeClass(); // wipe class attribute

.toggleClass()

.toggleClass(names [, force]) → self

Toggle classes, optionally forcing on/off with a boolean.

$('.menu').toggleClass('open');
$('.menu').toggleClass('open', isOpen);

.hasClass()

.hasClass(name) → boolean

True if any element in the set has the class.

if ($('#panel').hasClass('open')) close();
CSS & Geometry

Styles, sizes, positions, scrolling, visibility. Numbers get px automatically (except unitless properties like opacity); CSS custom properties (--vars) are supported.

.css()

.css(name [, value]) · .css(object) → string | self

Get a computed style from the first element, or set styles on all.

$('.card').css('color');            // computed
$('.card').css('margin-top', 20);   // → '20px'
$('.card').css({ opacity: .5, '--accent': 'red' });

.width() / .height()

.width([value]) · .height([value]) → number | self

Measured size (from getBoundingClientRect) or set the CSS size. On $(window), returns the viewport size.

$('.card').width();     // 320
$('.card').height(200); // set
$(window).width();      // viewport

.offset()

.offset() → { top, left }

Position relative to the document, including scroll.

const { top } = $('#hero').offset();

.position()

.position() → { top, left }

Position relative to the offset parent.

const p = $('.tooltip').position();

.scrollTop() / .scrollLeft()

.scrollTop([value]) · .scrollLeft([value]) → number | self

Get or set scroll position. Works on elements and on $(window).

$(window).scrollTop();      // read page scroll
$('#panel').scrollTop(0);   // scroll to top

.show() / .hide() / .toggle()

.show() · .hide() · .toggle([state]) → self

Instant visibility via display. .hide() remembers the previous display value so .show() restores it correctly.

$('.modal').show();
$('.hint').toggle();        // flip
$('.hint').toggle(isAdmin); // force
Insertion & Removal

All insertion methods accept HTML strings, elements, jsKjs sets, or plain text — and multiple arguments at once.

.append() / .prepend()

.append(...content) · .prepend(...content) → self

Insert content inside each element, at the end or the start.

$('#list').append('<li>End</li>');
$('#list').prepend($('<li>Start</li>'));

.before() / .after()

.before(...content) · .after(...content) → self

Insert content outside each element, as a previous or next sibling.

$('.section').before('<hr>');

.appendTo() / .prependTo()

.appendTo(target) · .prependTo(target) → self

Reversed form: insert this set into the target.

$('<li>New</li>').appendTo('#list');

.wrap()

.wrap(html) → self

Wrap each element in the given structure.

$('img').wrap('<figure class="frame">');

.remove()

.remove() → self

Remove elements from the DOM. Data cleanup is automatic (WeakMap).

$('.toast').remove();

.empty()

.empty() → self

Remove all children of each element.

$('#results').empty();

.clone()

.clone([deep = true]) → KJ

Deep-copy the elements.

$('#template-row').clone().appendTo('#table');

.replaceWith()

.replaceWith(content) → self

Replace each element with new content.

$('.old-banner').replaceWith('<div class="new">Hi</div>');
Traversal

Walk the tree. Every method returns a new chainable set; results are deduplicated.

.find()

.find(selector) → KJ

All descendants matching a selector.

$('#app').find('.btn').addClass('ready');

.filter()

.filter(selector | fn) → KJ

Keep only matching elements. Accepts a selector or a predicate (i, el) => boolean.

$('.item').filter('.active');
$('.item').filter((i, el) => el.dataset.price > 100);

.not()

.not(selector) → KJ

Drop matching elements.

$('.item').not('.sold-out').show();

.is()

.is(selector | element) → boolean

Test whether any element in the set matches.

if ($(e.target).is('button')) { … }

.closest()

.closest(selector) → KJ

Nearest matching ancestor (including the element itself). The backbone of event delegation.

$(e.target).closest('.card').addClass('selected');

.parent() / .parents()

.parent() · .parents([selector]) → KJ

Direct parent, or all ancestors (optionally filtered).

$('.btn').parent();
$('.btn').parents('.section');

.children()

.children([selector]) → KJ

Direct children, optionally filtered.

$('#list').children('li.active');

.siblings()

.siblings([selector]) → KJ

All siblings, optionally filtered.

$('.tab.active').siblings().removeClass('active');

.next() / .prev()

.next([selector]) · .prev([selector]) → KJ

Adjacent siblings, optionally required to match a selector.

$('.step.current').next().addClass('upcoming');
Events

Modern event handling with delegation, namespaces, once-only handlers, and custom events with payloads.

.on()

.on(types [, delegateSelector], handler) → self

Attach handlers. Multiple space-separated events and .namespace suffixes are supported. With a delegate selector, the handler fires for matching descendants — including ones added later — and this is the matched element.

$('.btn').on('click', e => save());
$('.btn').on('click.menu keydown.menu', handler);

// Delegation — survives DOM swaps
$('#list').on('click', '.item', function (e) {
  $(this).toggleClass('selected');
});

.one()

.one(types [, delegateSelector], handler) → self

Like .on() but the handler runs at most once.

$('#intro').one('click', dismiss);

.off()

.off([types] [, handler]) → self

Remove handlers — all of them, by event type, by namespace, or by specific handler reference.

$('.btn').off('click');
$('.btn').off('.menu');   // whole namespace
$('.btn').off();          // everything

.trigger()

.trigger(type [, detail]) → self

Dispatch an event (bubbling, cancelable). The optional payload arrives as the handler’s second argument.

$('#app').on('cart:add', (e, item) => render(item));
$('#app').trigger('cart:add', { sku: 'A-1' });

.hover()

.hover(enterFn [, leaveFn]) → self

Shorthand for mouseenter/mouseleave.

$('.card').hover(
  function () { $(this).addClass('lift'); },
  function () { $(this).removeClass('lift'); });

Shortcuts

.click([fn]) .change([fn]) .submit([fn]) … → self

With a handler: binds it. Without: triggers the event. Available for click, dblclick, change, input, submit, keydown, keyup, keypress, mousedown, mouseup, mousemove, mouseenter, mouseleave, scroll, resize, touchstart, touchend, contextmenu.

$('#save').click(() => submit());
$('#save').click();     // programmatic click

.focus() / .blur()

.focus([fn]) · .blur([fn]) → self

Bind a handler, or move focus when called without one.

$('#search').focus();          // focus the field
$('#search').focus(onFocus);   // bind
AJAX

Powered by fetch. Every call returns a native Promise (so await just works) with jQuery-style .done/.fail/.always shims attached.

$.ajax()

$.ajax(url | options [, options]) → Promise

Full-control requests. Options: url, method (or jQuery’s type), data (object → urlencoded or querystring; FormData; string), json: true (send JSON body), dataType (’json’ | ’auto’), headers, timeout (ms, auto-aborts), credentials, and callbacks success(data, status, res), error(err), complete(). The promise also has .abort().

const p = $.ajax({
  url: '/api/items', method: 'POST',
  data: { title: 'Hello' }, json: true,
  headers: { 'X-Token': 'abc' }, timeout: 5000,
});
p.done(d => render(d)).fail(err => alert(err.status));
// or simply:  const d = await p;

$.get()

$.get(url [, data] [, success]) → Promise

GET shorthand; data becomes the query string.

const html = await $.get('/partials/nav.html');
$.get('/api/search', { q: 'cats' }, render);

$.post()

$.post(url [, data] [, success]) → Promise

POST shorthand (urlencoded body by default).

await $.post('/api/save', { name: 'Ada' });

$.getJSON()

$.getJSON(url [, data] [, success]) → Promise

GET with forced JSON parsing.

const users = await $.getJSON('/api/users');

.load()

.load(url [ + ’ selector’] [, done]) → self

Fetch HTML into the element. Add a space + selector to insert only a fragment of the response.

$('#panel').load('/partials/news.html');
$('#panel').load('/page.html #main');

.serialize()

.serialize() → string

URL-encode a form’s fields.

$('#signup').serialize(); // "name=Ada&plan=pro"

.serializeObject()

.serializeObject() → object

A form’s fields as a plain object (jsKjs extra).

const { email } = $('#signup').serializeObject();
Hyper — Declarative AJAX

htmx-style: describe requests in HTML with kj-* attributes and never write the handler. A MutationObserver auto-binds content added later, including content swapped in by Hyper itself.

kj-get / kj-post / kj-put / kj-patch / kj-delete

kj-<verb>="/url"

The URL to request with that HTTP verb. Forms auto-serialize their fields; named inputs, selects and textareas send their own value. Default triggers: forms → submit, inputs/selects → change, everything else → click.

<button kj-get="/api/joke" kj-target="#out">Joke</button>

<form kj-post="/api/subscribe" kj-target="#msg">
  <input name="email" type="email">
  <button>Subscribe</button>
</form>

kj-target

kj-target="#selector"

Where the response HTML goes (default: the element itself).

<button kj-get="/api/stats" kj-target="#stats">Refresh</button>

kj-swap

kj-swap="innerHTML | outerHTML | textContent | beforebegin | afterbegin | beforeend | afterend | none"

How the response is inserted into the target. outerHTML replaces the target entirely; the four position values insert adjacent to it; none makes the request without touching the DOM.

<button kj-delete="/api/items/7" kj-target="#row-7"
        kj-swap="outerHTML">Delete</button>

kj-trigger

kj-trigger="event [delay:Nms] | load | revealed | every Ns"

When to fire: any DOM event (with optional debounce), load (immediately), revealed (when scrolled into view, via IntersectionObserver), or every Ns (polling).

<input name="q" kj-get="/api/search"
       kj-trigger="keyup delay:300ms" kj-target="#results">

<div kj-get="/api/comments" kj-trigger="revealed">…</div>
<span kj-get="/api/price" kj-trigger="every 10s"></span>

kj-confirm

kj-confirm="message"

Show a native confirm dialog before requesting.

<button kj-delete="/api/acct" kj-confirm="Really delete?">✕</button>

kj-indicator

kj-indicator="#selector"

Element to show while the request is in flight (the trigger also gets aria-busy="true").

<button kj-get="/slow" kj-indicator="#spinner">Go</button>
<span id="spinner" hidden>Loading…</span>

kj-include / kj-vals

kj-include="#form" · kj-vals=’{"k":"v"}’

Send extra data: the fields of another form, and/or literal JSON values.

<button kj-post="/api/filter" kj-include="#filters"
        kj-vals='{"page": 2}' kj-target="#grid">Next</button>

kj-push-url

kj-push-url="true | /path"

Push the request URL (or a given path) into browser history after a successful swap.

<a kj-get="/products?page=2" kj-target="#grid"
   kj-push-url="true">Page 2</a>

Lifecycle events

kj:before · kj:after · kj:error · kj:load

Fired on the triggering element (kj:before/after/error, with { url, verb, … } detail) and on the target after a swap (kj:load).

$('#btn').on('kj:error', (e, d) =>
  toast('Failed: ' + d.error.status));
$('#grid').on('kj:load', highlightNew);
Pulse — Reactivity

Alpine-style: declare state on an element with kj-data; bind it with directives. Mutating state re-renders the component. No virtual DOM, no build step. Inside expressions, $el is the element and $event the event.

kj-data

kj-data="{ … }" | kj-data="componentName"

Declares a component and its reactive scope. An init() method, if present, runs on mount. Pass a registered component name to reuse logic.

<div kj-data="{ count: 0, open: false }">…</div>
<div kj-data="dropdown">…</div>  <!-- registered -->

kj-text / kj-html

kj-text="expr" · kj-html="expr"

Bind textContent or innerHTML to an expression. Prefer kj-text for anything user-supplied.

<span kj-text="count"></span>
<p kj-text="name ? 'Hi ' + name : 'Who?'"></p>

kj-show

kj-show="expr"

Show/hide via display based on a truthy expression.

<ul kj-show="open">…</ul>

kj-model

kj-model="property"

Two-way binding for inputs, textareas, selects. Checkboxes bind booleans.

<input kj-model="email">
<input type="checkbox" kj-model="agreed">

@event / kj-on:event

@click="expr" · kj-on:input="expr" · modifiers: .prevent .stop .enter .escape

Run an expression on an event. Modifiers call preventDefault/stopPropagation or filter keys.

<button @click="count++">+1</button>
<form @submit.prevent="save()">…</form>
<input @keyup.enter="search($el.value)">

:attr / kj-bind:attr

:src="expr" · kj-bind:class="expr"

Bind any attribute to an expression. :class merges with the element’s static classes; false/null removes the attribute.

<img :src="user.avatar" :alt="user.name">
<button :disabled="saving">Save</button>
<div :class="open ? 'expanded' : ''">…</div>

$.component()

$.component(name, factory)

Register a reusable component factory, then reference it by name in kj-data.

$.component('counter', () => ({
  count: 0,
  init() { console.log('mounted'); },
}));
// <div kj-data="counter">…</div>

$.store()

$.store(name [, initial]) → reactive object

Create or retrieve a global reactive store. Any component reading it re-renders when it changes. Getters work as computed values.

const cart = $.store('cart', {
  items: [],
  get total() { return this.items.length; },
});
cart.items.push({ sku: 'A-1' }); // UI updates

$.reactive()

$.reactive(object) → proxy

A standalone reactive proxy without auto-rendering — for your own change-tracking logic.

const state = $.reactive({ x: 1 });
Motion — Animation

GSAP-style tweening on requestAnimationFrame. Transform shorthands (x, y, rotate, scale…) plus any numeric CSS property. Durations in seconds. All tweens return Promises.

$.to()

$.to(target, { …props, duration, delay, ease, stagger, onComplete }) → Promise

Tween to a state. stagger offsets each element’s start; onComplete fires after the last finishes. Also chainable on sets: $(sel).to(props).

$.to('.card', { x: 200, rotate: 10, opacity: .8,
                duration: .6, ease: 'back.out' });

await $.to('#modal', { opacity: 0, duration: .3 });
$('#modal').hide();

$.from()

$.from(target, props) → Promise

Jump to the given state, then tween back to the original — the classic entrance pattern.

$.from('.hero h1', { y: 40, opacity: 0,
  duration: .8, ease: 'power2.out' });

$.fromTo()

$.fromTo(target, fromProps, toProps) → Promise

Explicit start and end states.

$.fromTo('.badge', { scale: 0 },
  { scale: 1, duration: .5, ease: 'elastic.out' });

$.timeline()

$.timeline([defaults]) → timeline

Sequence tweens. Steps run one after another; pass position ’<’ to start a step together with the previous one. .add(fn) inserts arbitrary steps. Auto-plays.

$.timeline({ duration: .5, ease: 'power2.out' })
  .from('.hero',    { opacity: 0 })
  .from('.hero h1', { y: 30 })
  .from('.hero p',  { y: 30 }, '<')   // together
  .to('.cta',       { scale: 1.1 });

stagger

stagger: seconds

Offset each element in a multi-element tween — the signature "cascade" effect.

$.to('.item', { y: 0, opacity: 1,
  duration: .4, stagger: .08 });

Easings

ease: name | (t) => number

Built in: linear, ease-in, ease-out, ease-in-out, power2.in, power2.out, power2.inOut, back.out, elastic.out, bounce.out — or pass any function mapping 0→1 progress.

$.to('.ball', { y: 200, ease: 'bounce.out', duration: 1 });
$.to('.dot',  { x: 100, ease: t => t * t });
jQuery Effect Shims

The classics, rebuilt on the Motion engine. Durations in milliseconds, exactly as jQuery developers expect.

.fadeIn() / .fadeOut() / .fadeToggle()

.fadeIn([ms = 400] [, complete]) → self

Fade elements in (from hidden) or out (hiding when done).

$('.toast').fadeIn(300);
$('.toast').fadeOut(300, function () { $(this).remove(); });

.slideDown() / .slideUp() / .slideToggle()

.slideDown([ms = 400] [, complete]) → self

Animate height to reveal or collapse.

$('#faq-answer').slideToggle(250);

.animate()

.animate(props [, ms = 400] [, ease] [, complete]) → self

jQuery-signature tween of numeric CSS properties.

$('.box').animate({ marginLeft: 100, opacity: .5 }, 600);
Utilities

Small helpers on the $ namespace.

$.each()

$.each(arrayOrObject, (keyOrIndex, value) => {})

Iterate arrays, array-likes, or plain objects.

$.each({ a: 1, b: 2 }, (k, v) => console.log(k, v));

$.map()

$.map(collection, fn) → array

Map + flatten one level.

$.map([1, 2], n => [n, n * 10]); // [1,10,2,20]

$.extend()

$.extend([deep], target, …sources) → target

Merge objects; pass true first for deep merge.

$.extend(defaults, options);
$.extend(true, config, { api: { retries: 3 } });

$.debounce()

$.debounce(fn [, wait = 300]) → fn

Returns a function that fires only after calls stop for wait ms.

$('#q').on('input', $.debounce(search, 300));

$.throttle()

$.throttle(fn [, wait = 300]) → fn

Returns a function that fires at most once per wait ms.

$(window).on('scroll', $.throttle(onScroll, 100));

$.param()

$.param(object) → string

Serialize an object to a query string.

$.param({ a: 1, b: 'x y' }); // "a=1&b=x+y"

$.parseHTML()

$.parseHTML(html) → element[]

Parse an HTML string into an array of nodes.

const [li] = $.parseHTML('<li>Hi</li>');

$.escape()

$.escape(string) → string

HTML-escape text — use it whenever you string-build HTML from user data.

$('#out').html('<b>' + $.escape(userInput) + '</b>');

$.uuid()

$.uuid() → string

A cryptographically strong UUID (v4).

const id = $.uuid();

Type checks

$.isArray(x) · $.isFunction(x) · $.isPlainObject(x) · $.trim(s)

Small predicates and string trim, kept for jQuery compatibility.

$.isPlainObject({});   // true
$.isArray('nope');     // false

$.noConflict()

$.noConflict() → $

Restore the previous window.$ and return jsKjs (also always available as kj and jsKjs).

const j = $.noConflict();
j('#app').addClass('ready');

$.version

$.version → string

The library version.

console.log($.version); // "1.0.0"

Browser support & guarantees

jsKjs targets evergreen browsers: Chrome 90+, Firefox 90+, Safari 15+, Edge 90+. Internet Explorer and pre-2021 browsers are unsupported by design — that is where the 7.7 KB footprint comes from. The full jQuery-3-era API that remains in common use is covered; long-deprecated APIs (live(), bind(), $.Deferred) are intentionally omitted in favour of native Promises and delegation.