A tiny DOM event utility with sugar.
Write clean event bindings using fluent On.click(...), On.first.keydown(...), or classic on(el, 'click', fn).
on(el, 'click', fn)— classic bindingOn.click(el, fn)— fluent sugar per event nameOn.first.click(el, fn)— fires once then unbindsOn.delegate.click(el, selector, fn)— delegated eventsOn.capture.focus(el, fn)— capture-phase listenerOn.hover(el, enter, leave)— mouseenter/leave pairOn.batch(el, { click, ... })— multi-bind at onceOn.first.batch(...)— one-time multi-bindOn.passive.scroll(el, fn)— optimized scroll/touchOn.ready(fn)— run when DOM is ready- ESM, zero dependencies, < 1KB min+gzip
npm install on-eventsimport { on, off } from 'on-events'
const stop = on(window, 'keydown', (e) => {
console.log('Pressed:', e.key)
})
stop() // unbindsimport { On } from 'on-events'
// Basic
On.click(button, () => console.log('Clicked'))
// Fires once
On.first.submit(form, () => console.log('Submitted once'))
// Delegate
On.delegate.click(document, 'button.action', (e) => {
console.log('Clicked', e.target.textContent)
})
// Capture
On.capture.focus(input, () => console.log('Focus (captured)'))
// Hover
const stopHover = On.hover(card,
() => card.classList.add('hover'),
() => card.classList.remove('hover')
)const stop = On.batch(window, {
click: () => console.log('Window clicked'),
keydown: (e) => console.log('Key:', e.key)
})
// Unbind all
stop()On.first.batch(document, {
scroll: () => console.log('First scroll'),
keyup: () => console.log('First keyup')
})On.passive.scroll(window, () => console.log('Smooth scroll'))
On.passive.touchstart(document, e => console.log('Touch start'))On.ready(() => {
console.log('DOM fully loaded')
})Adds a standard or delegated event listener. Returns a stop function.
Removes a previously added listener.
Fluent alias for on(el, 'event', handler).
Example: On.click(el, fn).
Same as On.event, but auto-removes after first call.
Example: On.first.keydown(el, fn)
Binds a delegated event using closest(selector).
Adds a listener during the capture phase.
Convenience for mouseenter and mouseleave.
Bind multiple events at once:
On.batch(el, {
click: fn1,
keydown: fn2
})One-time version of batch():
On.first.batch(el, {
scroll: onceScroll,
input: onceInput
})Adds a listener with { passive: true }, ideal for:
scrolltouchstartwheel
Runs fn once the DOM is fully loaded (DOMContentLoaded or already ready).
On.once.*is still available as a backward-compatible alias forOn.first.*
--{DR.WATT v3.0}--