custom-event
custom-event is a tiny CommonJS compatibility constructor for DOM CustomEvent objects. It exports the browser's native constructor when a quick feature test succeeds, otherwise it falls back to document.createEvent and initCustomEvent for IE 9 and newer, with a separate createEventObject path for IE 8. It carries a value in event.detail, but it is not an event bus, listener registry, Node EventEmitter, or full DOM shim.
Keep custom-event when an old browser bundle already depends on its IE fallbacks. For a new application targeting current browsers, the native constructor is the clearer choice and costs no dependency.
Use it if
- You maintain a browser bundle that must still create CustomEvent objects on Internet Explorer
- A transitive dependency already expects require('custom-event') and replacing that call would add needless churn
- You need one CommonJS import that uses the native constructor when it works and falls back when it does not
- You are repairing an older application whose build and test matrix already includes this exact package
- You only support current browsers: the platform CustomEvent constructor already supplies the API this package wraps, so installing a compatibility layer adds no useful capability
- You need an event emitter or pub/sub system: the README only creates an event and dispatches it through a DOM EventTarget, and the package provides no on, off, once, or emit methods
- You need TypeScript declarations: version 1.0.1 declares no types field and ships no declaration file, so typed projects must add a local module declaration or rely on inference around require
- You need a DOM implementation in Node: open issues #4 and #5 ask for no-global and Node versions, while the fallback source calls document.createEventObject when the native global constructor is unavailable
- You require actively maintained dependencies: the last repository push and npm release were in October 2016, three open requests remain, and the test tool is an old Zuul 1.x dev dependency
Setup reality
Installation is only npm install custom-event, and runtime version 1.0.1 has no dependencies or peer dependencies. The import is CommonJS: var CustomEvent = require('custom-event'). In an older browser bundle, Browserify, webpack, or another CommonJS-aware build step must turn that require into browser code; the package does not publish an ESM entry, browser field, TypeScript declaration, or ready-to-copy minified browser file. Its startup feature test reads global.CustomEvent and tries to construct an event. If that fails, it selects a document-based fallback. That is useful in IE, but it does not create a document for Node, workers, or server rendering. In an environment with neither a usable native CustomEvent nor document, construction reaches document.createEventObject and throws. Importing can still appear safe because document is read inside the fallback function, so the surprise may wait until the first new CustomEvent call. The IE 9 path maps params.bubbles, params.cancelable, and params.detail into initCustomEvent; omitted options become false, false, and undefined. The IE 8 branch only creates an event-like object, so do not assume every modern Event method or propagation behavior is present. There is no configuration file, build hook, native compilation, credential, or production service to set up. The real setup decision is whether your supported browser list still contains the legacy engines this seven-line public API exists to cover. If it does not, use globalThis.CustomEvent directly and remove the dependency.
Patterns
Install the constructorinstall-package
npm install custom-eventVersion 1.0.1 has no runtime or peer dependencies, but the published entry point is CommonJS.
Import from CommonJSimport-constructor
var CustomEvent = require('custom-event');There is no ESM export or TypeScript declaration in the package metadata.
Dispatch structured detaildispatch-detail
var CustomEvent = require('custom-event');
var event = new CustomEvent('cart:add', {
detail: { sku: 'A-42', quantity: 2 }
});
document.dispatchEvent(event);The payload belongs in detail; adding arbitrary top-level properties is not the CustomEvent API.
Read detail in a listenerlisten-for-event
document.addEventListener('cart:add', function (event) {
console.log(event.detail.sku, event.detail.quantity);
});Register the listener on the same target, or an ancestor when the custom event is configured to bubble.
Create a bubbling eventenable-bubbling
var event = new CustomEvent('menu:select', {
bubbles: true,
detail: { value: 'settings' }
});
button.dispatchEvent(event);bubbles defaults to false in both fallback branches, so delegation requires setting it explicitly.
Create a cancelable eventmake-cancelable
var event = new CustomEvent('dialog:before-close', {
cancelable: true,
detail: { reason: 'escape' }
});
var accepted = dialog.dispatchEvent(event);
if (!accepted) console.log('close was canceled');A listener must call preventDefault, and cancelable must be true, for dispatchEvent to return false.
Cancel a proposed actioncancel-in-listener
dialog.addEventListener('dialog:before-close', function (event) {
if (hasUnsavedChanges()) event.preventDefault();
});Do not depend on modern Event methods in the package's IE 8 createEventObject branch without testing that browser path.
Delegate a bubbling custom eventdelegate-event
list.addEventListener('row:activate', function (event) {
console.log('activated', event.detail.id);
});
row.dispatchEvent(new CustomEvent('row:activate', {
bubbles: true,
detail: { id: 17 }
}));The event only reaches list when row is a descendant and bubbles is enabled.
Dispatch from a specific elementdispatch-from-element
var input = document.querySelector('#search');
input.dispatchEvent(new CustomEvent('search:clear', {
detail: { previousValue: input.value }
}));The package constructs the event only; dispatchEvent is supplied by the DOM target.
Construct an event without optionsomit-options
var ready = new CustomEvent('widget:ready');
widget.dispatchEvent(ready);The fallbacks set bubbles and cancelable to false and detail to undefined when params is omitted.
Pass the event to platform codebridge-native-code
function announce(target, name, data) {
target.dispatchEvent(new CustomEvent(name, { detail: data }));
}
announce(window, 'session:expired', { at: Date.now() });The export is the native constructor when its startup feature test succeeds, so consumers use the normal DOM event contract.
Avoid construction during server renderingguard-server-rendering
if (typeof document !== 'undefined') {
var CustomEvent = require('custom-event');
document.dispatchEvent(new CustomEvent('app:hydrated'));
}When no usable native global exists, construction needs document; the package does not provide a server-side DOM.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| custom-event-polyfill | npm | Choose it when you want a side-effect polyfill for IE 9 and newer instead of changing every constructor import |
| event-target-shim | npm | Choose it when the missing piece is a WHATWG-style EventTarget implementation, not just CustomEvent construction |
| eventemitter3 | npm | Choose it for application-level events across Node and browsers where DOM propagation semantics are unnecessary |