Core Β· jQuery-compatible

Custom events

Announce what happened with .trigger('cart:add', item) and let any number of independent listeners react. The button doesn't need to know who is listening.

.trigger(type, detail) dispatches a native, bubbling CustomEvent. Listeners receive the payload as their second argument, so (e, item) => … reads naturally. Because the event bubbles, a single listener on document hears announcements from anywhere on the page.

This pattern keeps features independent: the cart badge, a toast system and analytics can each subscribe to cart:add without importing each other. Add or remove a listener and nothing else changes.

Live Β· One event, three independent listeners

Shop πŸ›’ 0 in cart
View the source for this demo
HTML
<div class="row" style="justify-content:space-between">
  <strong>Shop</strong>
  <span class="chip">πŸ›’ <span id="ce-count">0</span> in cart</span>
</div>
<div class="ce-grid" id="ce-products" style="margin-top:12px">
  <button type="button" data-sku="TEE" data-price="24">Tween Tee</button>
  <button type="button" data-sku="MUG" data-price="18">Easing Mug</button>
  <button type="button" data-sku="MAT" data-price="32">Deskmat</button>
</div>
<div id="ce-toasts" role="status" aria-live="polite"></div>
<pre class="out" id="ce-log"></pre>
JavaScript
// Listener 1 β€” cart badge
$(document).on('cart:add', () => $('#ce-count').text(+$('#ce-count').text() + 1));

// Listener 2 β€” toast
$(document).on('cart:add', (e, item) => {
  const $t = $('<div class="toast">').text('Added ' + item.name + ' Β· $' + item.price).appendTo('#ce-toasts');
  $.fromTo($t, { y: 12, opacity: 0 }, { y: 0, opacity: 1, duration: .25 });
  setTimeout(() => $t.fadeOut(300, function () { $(this).remove(); }), 2200);
});

// Listener 3 β€” "analytics"
$(document).on('cart:add', (e, item) => {
  $('#ce-log').text('analytics ← cart:add ' + JSON.stringify(item) + '\n' + $('#ce-log').text());
});

// The buttons only announce what happened
$('#ce-products').on('click', 'button', function () {
  $(this).trigger('cart:add', { sku: this.dataset.sku, name: $(this).text(), price: +this.dataset.price });
});

More examples

Namespaced app events

JavaScript
$(document).on('auth:login', (e, user) => $('#avatar').attr('src', user.avatar));
$(document).on('auth:logout', () => location.assign('/'));
$('#login-form').trigger('auth:login', { name: 'Ada', avatar: '/a.png' });

API

.trigger(type [, detail]) β†’ self

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

Reference: .trigger() β†’
.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.

Reference: .on() β†’

Migrating

Coming from jQueryjQuery passes extra parameters as an array (trigger("x", [a, b])). jsKjs passes one payload β€” use an object β€” available as e.detail and as the handler's second argument.

Related features