GitPedia

Spect

Observable selectors in DOM

From dy·Updated January 30, 2026·View on GitHub·

Observes _`selector`_ in _`container`_, invokes `handler` for matched elements, which can return a teardown function called when elements unmatch. Returns live collection of elements. The project is written primarily in JavaScript, distributed under the MIT License license, first published in 2019. Key topics include: aspects, live-collection, selector-observer, spect.

Latest release: v24.1.0v24.0.1
January 16, 2022View Changelog →

<sub><img alt="spect" src="./logo2.svg" height=30 /></sub> spect <a href="https://github.com/spectjs/spect/actions/workflows/test.yml"><img src="https://github.com/spectjs/spect/actions/workflows/test.yml/badge.svg"/></a> <img alt="npm bundle size" src="https://img.shields.io/bundlejs/size/spect"> <a href="https://npmjs.org/package/spect"><img alt="npm" src="https://img.shields.io/npm/v/spect"></a>

Observe selectors in DOM.

spect( container=document, selector, handler? )

Observes selector in container, invokes handler for matched elements, which can return a teardown function called when elements unmatch.<br/>
Returns live collection of elements.

js
import spect from 'spect'; // assign aspect const foos = spect('.foo', el => { console.log('connected'); return () => console.log('disconnected'); }); // modify DOM const foo = document.createElement('div'); foo.className = 'foo'; document.body.append(foo); // ... "connected" foo.remove(); // ... "disconnected"

spect(element[s], handler)

Listens for connected/disconnected events for the list of elements. (alternative to fast-on-load)

js
const nodes = [...document.querySelectorAll('.foo'), document.createElement('div')]; // assign listener spect(nodes, el => { console.log("connected"); return () => console.log("disconnected"); }); document.body.appendChild(nodes.at(-1)) // ... "connected" nodes.at(-1).remove() // ... "disconnected"

Live Collection

Spect creates live collection of elements matching the selector. Collection extends Array and implements Set / HTMLColection interfaces.

js
const foos = spect(`.foo`); // live collection foos[idx], foos.at(idx) // Array foos.has(el), foos.add(el), foos.delete(el) // Set foos.item(idx), foos.namedItem(elementId) // HTMLCollection foos.dispose() // destroy selector observer / unsubscribe

Technique

Selector parts indexing from selector-observer for simple queries and animation events from insertionQuery for complex selectors.

Simple selector is id/name/class/tag followed by classes or attrs.

  • #a, .x.y, [name="e"].x, *, a-b-c:x - simple selectors.
  • a b, #b .c - complex selectors.
<!-- ## Examples <details><summary>Hello World</summary> ```html <div class="user">{{ user.name || "Loading..." }}</div> <script type="module"> import spect from 'spect' import templize from 'templize' // initialize template spect('.user', async el => templize(el, { user: (await fetch('/user')).json() // value is available when resolved })) </script> ``` </details> <details><summary>Timer</summary> ```html <time class="timer">{{ count }}</time> <time class="timer">{{ count }}</time> <script type="module"> import spect from 'spect' import templize from 'templize' spect('.timer', timer => { const params = templize(timer, { count: 0 }) const id = setInterval(() => params.count++, 1000) return () => clearInterval(id) }) </script> ``` </details> <details><summary>Counter</summary> ```html <output id="count">{{ count }}</output> <button id="inc" onclick="{{ inc }}">+</button> <button id="dec" onclick="{{ dec }}">-</button> <script type="module"> import spect from 'spect' import v from 'value-ref' import templize from 'templize' const count = v(0) spect('#count', el => templize(el, { count })) // bind events via HTML template spect('#inc', el => templize(el, { inc: () => count.value++ })) spect('#dec', el => templize(el, { dec: () => count.value-- })) </script> ``` </details> <details><summary>Todo list</summary> ```html <form class="todo-form"> <label for="add-todo"> <span>Add Todo</span> <input name="text" required> </label> <button type="submit">Add</button> <ul class="todo-list">{{ todos }}<ul> </form> <script type="module"> import spect from 'spect' import v from 'value-ref' import h from 'hyperf' import tpl from 'templize' const todos = v([]) spect('.todo-list', el => tpl(el, { todos: v.from(todos, item => h`<li>${ item.text }</li>`) })) spect('.todo-form', form => form.addEventListener('submit', e => { e.preventDefault() if (!form.checkValidity()) return todos.value = [...todos.value, { text: form.text.value }] form.reset() })) </script> ``` </details> <details><summary>Form validator</summary> ```html <form id="email-form"> <label for="email">Please enter an email address:</label> <input id="email" onchange={{ validate }}/> The address is {{ valid ? "valid" : "invalid" }} </form> <script type="module"> import spect from 'spect' import templize from 'templize' const isValidEmail = s => /.+@.+\..+/i.test(s) spect('#email-form', form => { const params = templize(form, { valid: false, validate: () => params.valid = isValidEmail(e.target.value) }) }) </script> ``` </details> <details><summary>Prompt</summary> ```html <dialog class="dialog" open={{showPrompt}}> Proceed? <menu> <button onclick={{cancel}}>Cancel</button> <button onclick={{confirm}}>Confirm</button> </menu> </dialog> <script> import v from 'value-ref' import spect from 'spect' spect('.dialog', el => { const showPrompt = v(false), proceed = v(false) templize(el, { showPrompt, proceed, cancel() {showPrompt.value = proceed.value = false;}, confirm() {showPrompt.value = false; proceed.value = true;} }) }) </script> ``` </details> [See all examples](examples). --> <!-- ## Best Buddies * [value-ref](https://github.com/spectjs/value-ref) − value container with observable interface. Indispensible for reactive data. * [templize](https://github.com/spectjs/templize) − DOM buddy - hooks up reactive values to template parts. * [hyperf](https://github.com/spectjs/hyperf) − builds HTML fragments with reactive fields. * [subscribable-things](https://github.com/chrisguttandin/subscribable-things) − collection of observables for different browser APIs. --> <!-- * [element-props](https://github.com/spectjs/element-props) − unified access to element props with observable support. Comes handy for organizing components. --> <!-- * [strui](https://github.com/spectjs/strui) − collection of UI streams, such as router, storage etc. Comes handy for building complex reactive web-apps (spect, rxjs etc). -->

Alternatives

element-behaviors,
insertionQuery,
selector-observer,
qso,
qsa-observer,
element-observer,
livequery,
selector-listener,
mutation-summary,
fast-on-load,
selector-set,
rkusa/selector-observer,
css-chain

<p align="center"><a href="https://krishnized.com/license/">ॐ</a></p>

Contributors

Showing top 5 contributors by commit count.

View all contributors on GitHub →

This article is auto-generated from dy/spect via the GitHub API.Last fetched: 6/23/2026