Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

delegate-it

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

delegate-it - npm Package Compare versions

Comparing version 5.0.0 to 6.0.0

delegate.d.ts

16

index.d.ts

@@ -1,14 +0,2 @@

import type { ParseSelector } from 'typed-query-selector/parser.d.js';
export declare type DelegateOptions = boolean | Omit<AddEventListenerOptions, 'once'>;
export declare type EventType = keyof GlobalEventHandlersEventMap;
export declare type DelegateEventHandler<TEvent extends Event = Event, TElement extends Element = Element> = (event: DelegateEvent<TEvent, TElement>) => void;
export declare type DelegateEvent<TEvent extends Event = Event, TElement extends Element = Element> = TEvent & {
delegateTarget: TElement;
};
/**
* Delegates event to a selector.
* @param options A boolean value setting options.capture or an options object of type AddEventListenerOptions without the `once` option
*/
declare function delegate<Selector extends string, TElement extends Element = ParseSelector<Selector, HTMLElement>, TEventType extends EventType = EventType>(base: EventTarget | Document | Iterable<Element> | string, selector: Selector, type: TEventType, callback: DelegateEventHandler<GlobalEventHandlersEventMap[TEventType], TElement>, options?: DelegateOptions): void;
declare function delegate<TElement extends Element = HTMLElement, TEventType extends EventType = EventType>(base: EventTarget | Document | Iterable<Element> | string, selector: string, type: TEventType, callback: DelegateEventHandler<GlobalEventHandlersEventMap[TEventType], TElement>, options?: DelegateOptions): void;
export default delegate;
export * from './delegate.js';
export { default as oneEvent } from './one-event.js';

@@ -1,80 +0,2 @@

/** Keeps track of raw listeners added to the base elements to avoid duplication */
const ledger = new WeakMap();
function editLedger(wanted, baseElement, callback, setup) {
if (!wanted && !ledger.has(baseElement)) {
return false;
}
const elementMap = ledger.get(baseElement)
?? new WeakMap();
ledger.set(baseElement, elementMap);
if (!wanted && !ledger.has(baseElement)) {
return false;
}
const setups = elementMap.get(callback) ?? new Set();
elementMap.set(callback, setups);
const existed = setups.has(setup);
if (wanted) {
setups.add(setup);
}
else {
setups.delete(setup);
}
return existed && wanted;
}
function isEventTarget(elements) {
return typeof elements.addEventListener === 'function';
}
function safeClosest(event, selector) {
let target = event.target;
if (target instanceof Text) {
target = target.parentElement;
}
if (target instanceof Element && event.currentTarget instanceof Element) {
// `.closest()` may match ancestors of `currentTarget` but we only need its children
const closest = target.closest(selector);
if (closest && event.currentTarget.contains(closest)) {
return closest;
}
}
}
// This type isn't exported as a declaration, so it needs to be duplicated above
function delegate(base, selector, type, callback, options) {
const listenerOptions = typeof options === 'object' ? options : { capture: options };
// Drop unsupported `once` option https://github.com/fregante/delegate-it/pull/28#discussion_r863467939
delete listenerOptions.once;
const { signal } = listenerOptions;
if (signal?.aborted) {
return;
}
// Handle Selector-based usage
if (typeof base === 'string') {
base = document.querySelectorAll(base);
}
// Handle Array-like based usage
if (!isEventTarget(base)) {
for (const element of base) {
delegate(element, selector, type, callback, listenerOptions);
}
return;
}
// `document` should never be the base, it's just an easy way to define "global event listeners"
const baseElement = base instanceof Document ? base.documentElement : base;
// Handle the regular Element usage
const capture = Boolean(typeof options === 'object' ? options.capture : options);
const listenerFn = (event) => {
const delegateTarget = safeClosest(event, selector);
if (delegateTarget) {
const delegateEvent = Object.assign(event, { delegateTarget });
callback.call(baseElement, delegateEvent);
}
};
const setup = JSON.stringify({ selector, type, capture });
const isAlreadyListening = editLedger(true, baseElement, callback, setup);
if (!isAlreadyListening) {
baseElement.addEventListener(type, listenerFn, listenerOptions);
}
signal?.addEventListener('abort', () => {
editLedger(false, baseElement, callback, setup);
});
}
export default delegate;
export * from './delegate.js';
export { default as oneEvent } from './one-event.js';
{
"name": "delegate-it",
"version": "5.0.0",
"version": "6.0.0",
"description": "Lightweight and modern event delegation in the browser",

@@ -19,10 +19,16 @@ "keywords": [

"repository": "fregante/delegate-it",
"funding": "https://github.com/sponsors/fregante",
"license": "MIT",
"author": "Federico Brigante <me@fregante.com> (https://fregante.com)",
"type": "module",
"main": "index.js",
"module": "index.js",
"exports": "./index.js",
"main": "./index.js",
"types": "./index.d.ts",
"files": [
"index.js",
"index.d.ts"
"index.d.ts",
"delegate.js",
"delegate.d.ts",
"one-event.js",
"one-event.d.ts"
],

@@ -32,6 +38,5 @@ "scripts": {

"prepack": "tsc --sourceMap false",
"test": "tsc && xo && ava",
"watch": "run-p --silent watch:*",
"watch:build": "tsc --watch",
"watch:test": "ava --watch"
"test": "tsc && xo && vitest run",
"watch": "tsc --watch",
"watch:test": "vitest"
},

@@ -48,13 +53,12 @@ "xo": {

"dependencies": {
"typed-query-selector": "^2.6.1"
"typed-query-selector": "^2.10.0"
},
"devDependencies": {
"@sindresorhus/tsconfig": "^3.0.1",
"ava": "^4.3.0",
"jsdom": "^20.0.0",
"npm-run-all": "^4.1.5",
"sinon": "^14.0.0",
"typescript": "^4.7.4",
"xo": "^0.50.0"
"@types/jsdom": "^21.1.1",
"jsdom": "^21.1.1",
"typescript": "^5.0.4",
"vitest": "^0.30.1",
"xo": "^0.54.1"
}
}

@@ -8,5 +8,5 @@ # delegate-it [![][badge-gzip]][link-bundlephobia]

This is a fork of the popular [`delegate`](https://github.com/zenorocha/delegate) with some improvements:
This is a fork of the popular but abandoned [`delegate`](https://github.com/zenorocha/delegate) with some improvements:
- modern: ES2021, TypeScript, Edge 16+ (it uses `WeakMap` and `Element.closest()`)
- modern: ES2022, TypeScript, Edge 16+ (it uses `WeakMap` and `Element.closest()`)
- idempotent: identical listeners aren't added multiple times, just like the native `addEventListener`

@@ -33,6 +33,4 @@ - debugged ([2d54c11](https://github.com/fregante/delegate-it/commit/2d54c1182aefd3ec9d8250fda76290971f5d7166), [c6bb88c](https://github.com/fregante/delegate-it/commit/c6bb88c2aa8097b25f22993a237cf09c96bcbfb8))

#### With an element as base
```js
delegate(document.body, '.btn', 'click', event => {
delegate('.btn', 'click', event => {
console.log(event.delegateTarget);

@@ -42,40 +40,32 @@ });

#### With a selector (of existing elements) as base
### With listener options
```js
delegate('.container', '.btn', 'click', event => {
delegate('.btn', 'click', event => {
console.log(event.delegateTarget);
}, {
capture: true
});
```
#### With an array/array-like of elements as base
### On a custom base
```js
delegate(document.querySelectorAll('.container'), '.btn', 'click', event => {
console.log(event.delegateTarget);
});
```
Use this option if you don't want to have a global listener attached on `html`, it improves performance:
#### With listener options
```js
delegate(document.body, '.btn', 'click', event => {
delegate('.btn', 'click', event => {
console.log(event.delegateTarget);
}, true);
// Or equivalent:
delegate(document.body, '.btn', 'click', event => {
console.log(event.delegateTarget);
}, {
capture: true
base: document.querySelector('main')
});
```
**Note:** the `once` option is currently not supported.
### Remove event delegation
```js
const controller = delegate(document.body, '.btn', 'click', event => {
const controller = new AbortController();
delegate('.btn', 'click', event => {
console.log(event.delegateTarget);
}, {
signal: controller.signal,
});

@@ -86,14 +76,22 @@

### Listen to one event only
```js
const controller = new AbortController();
delegate(document.body, '.btn', 'click', event => {
console.log(event.delegateTarget);
delegate('.btn', 'click', event => {
console.log('This will only be called once');
}, {
signal: controller.signal,
once: true
});
```
controller.abort();
### Listen to one event only, with a promise
```js
import {oneEvent} from 'delegate-it';
await oneEvent('.btn', 'click');
console.log('The body was clicked');
```
### Custom event types in Typescript
## TypeScript

@@ -100,0 +98,0 @@ If you're using TypeScript and have event types that are custom, you can override the global `GlobalEventHandlersEventMap` interface via declaration merging. e.g. say you have a `types/globals.d.ts` file, you can add the following.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc