consolidated-events
Advanced tools
Comparing version 1.0.1 to 1.1.0
@@ -1,2 +0,1 @@ | ||
/* eslint-disable import/first */ | ||
import { addEventListener, removeEventListener, EVENT_HANDLERS_KEY } from '../src'; | ||
@@ -28,8 +27,7 @@ import TargetEventHandlers from '../src/TargetEventHandlers'; | ||
it('returns a handle', () => { | ||
it('returns an unsubscribe function', () => { | ||
const target = new MockTarget(); | ||
const handle = addEventListener(target, 'scroll', () => {}, { capture: true }); | ||
const remove = addEventListener(target, 'scroll', () => {}, { capture: true }); | ||
expect(handle).not.toBe(null); | ||
expect(handle).not.toBe(undefined); | ||
expect(typeof remove).toBe('function'); | ||
}); | ||
@@ -39,11 +37,6 @@ }); | ||
describe('removeEventListener()', () => { | ||
it('does not throw when target is undefined', () => { | ||
const handle = { target: undefined }; | ||
expect(() => removeEventListener(handle)).not.toThrow(); | ||
}); | ||
it('removes event listeners that were previously registered', () => { | ||
const target = new MockTarget(); | ||
const handle = addEventListener(target, 'scroll', () => {}); | ||
removeEventListener(handle); | ||
const unsubscribe = addEventListener(target, 'scroll', () => {}); | ||
removeEventListener(unsubscribe); | ||
@@ -57,4 +50,4 @@ expect(target.removeEventListener) | ||
addEventListener(target, 'scroll', () => {}); | ||
removeEventListener({ target, eventName: 'scroll', index: 'foo' }); | ||
removeEventListener({ target, eventName: 'resize', index: 'foo' }); | ||
removeEventListener(() => {}); | ||
removeEventListener(() => {}); | ||
@@ -66,4 +59,4 @@ expect(target.removeEventListener).toHaveBeenCalledTimes(0); | ||
const target = new MockTarget(); | ||
const handle = addEventListener(target, 'scroll', () => {}, { capture: true }); | ||
removeEventListener(handle); | ||
const unsubscribe = addEventListener(target, 'scroll', () => {}, { capture: true }); | ||
removeEventListener(unsubscribe); | ||
@@ -70,0 +63,0 @@ expect(target.removeEventListener) |
@@ -11,11 +11,2 @@ import TargetEventHandlers from '../src/TargetEventHandlers'; | ||
describe('#add()', () => { | ||
it('returns a handle', () => { | ||
const target = new MockTarget(); | ||
const eventHandlers = new TargetEventHandlers(target); | ||
const handle = eventHandlers.add('scroll', () => {}); | ||
expect(handle).not.toBe(null); | ||
expect(handle).not.toBe(undefined); | ||
}); | ||
it('adds a single event listener to the target the first time', () => { | ||
@@ -74,11 +65,17 @@ const target = new MockTarget(); | ||
}); | ||
}); | ||
describe('#delete()', () => { | ||
it('deletes the event listener when the only handler is removed', () => { | ||
it('returns an unsubscribe function', () => { | ||
const target = new MockTarget(); | ||
const eventHandlers = new TargetEventHandlers(target); | ||
const handle = eventHandlers.add('scroll', () => {}); | ||
eventHandlers.delete(handle); | ||
const remove = eventHandlers.add('scroll', () => {}); | ||
expect(typeof remove).toBe('function'); | ||
}); | ||
it('unsubscribe deletes the event listener when the only handler is removed', () => { | ||
const target = new MockTarget(); | ||
const eventHandlers = new TargetEventHandlers(target); | ||
const remove = eventHandlers.add('scroll', () => {}); | ||
remove(); | ||
expect(target.removeEventListener).toHaveBeenCalledTimes(1); | ||
@@ -89,7 +86,17 @@ expect(target.removeEventListener) | ||
it('does not delete the listener when removing an unknown handler', () => { | ||
it('unsubscribe does not throw when called twice', () => { | ||
const target = new MockTarget(); | ||
const eventHandlers = new TargetEventHandlers(target); | ||
const remove = eventHandlers.add('scroll', () => {}); | ||
remove(); | ||
expect(remove).not.toThrow(); | ||
}); | ||
it('unsubscribe does not delete the event listener when there are more handlers left', () => { | ||
const target = new MockTarget(); | ||
const eventHandlers = new TargetEventHandlers(target); | ||
const remove = eventHandlers.add('scroll', () => {}); | ||
eventHandlers.add('scroll', () => {}); | ||
eventHandlers.delete({ target: 'foo' }); | ||
remove(); | ||
@@ -99,8 +106,9 @@ expect(target.removeEventListener).toHaveBeenCalledTimes(0); | ||
it('does not delete the event listener when there are more handlers left', () => { | ||
it('unsubscribe called multiple times does not delete the event listener when there are more handlers left', () => { | ||
const target = new MockTarget(); | ||
const eventHandlers = new TargetEventHandlers(target); | ||
const handle = eventHandlers.add('scroll', () => {}); | ||
const remove = eventHandlers.add('scroll', () => {}); | ||
eventHandlers.add('scroll', () => {}); | ||
eventHandlers.delete(handle); | ||
remove(); | ||
remove(); | ||
@@ -110,9 +118,9 @@ expect(target.removeEventListener).toHaveBeenCalledTimes(0); | ||
it('deletes the event listener when all handlers is removed', () => { | ||
it('unsubscribe deletes the event listener when all handlers are removed', () => { | ||
const target = new MockTarget(); | ||
const eventHandlers = new TargetEventHandlers(target); | ||
const handle = eventHandlers.add('scroll', () => {}); | ||
const handle2 = eventHandlers.add('scroll', () => {}); | ||
eventHandlers.delete(handle); | ||
eventHandlers.delete(handle2); | ||
const remove = eventHandlers.add('scroll', () => {}); | ||
const remove2 = eventHandlers.add('scroll', () => {}); | ||
remove(); | ||
remove2(); | ||
@@ -124,9 +132,9 @@ expect(target.removeEventListener).toHaveBeenCalledTimes(1); | ||
it('handles different options separately', () => { | ||
it('unsubscribe handles different options separately', () => { | ||
const target = new MockTarget(); | ||
const eventHandlers = new TargetEventHandlers(target); | ||
const handle = eventHandlers.add('scroll', () => {}); | ||
const handle2 = eventHandlers.add('scroll', () => {}, { passive: true }); | ||
eventHandlers.delete(handle); | ||
eventHandlers.delete(handle2); | ||
const remove = eventHandlers.add('scroll', () => {}); | ||
const remove2 = eventHandlers.add('scroll', () => {}, { passive: true }); | ||
remove(); | ||
remove2(); | ||
@@ -133,0 +141,0 @@ expect(target.removeEventListener).toHaveBeenCalledTimes(2); |
@@ -0,1 +1,6 @@ | ||
## v1.1.0 | ||
- Return an unsubscribe function from `addEventListener` and deprecate | ||
`removeEventListener`. | ||
## v1.0.1 | ||
@@ -2,0 +7,0 @@ |
@@ -19,2 +19,6 @@ Object.defineProperty(exports, "__esModule", { | ||
if (!window.addEventListener || !window.removeEventListener || !Object.defineProperty) { | ||
return false; | ||
} | ||
var supportsPassiveOption = false; | ||
@@ -21,0 +25,0 @@ try { |
@@ -30,14 +30,5 @@ Object.defineProperty(exports, "__esModule", { | ||
function removeEventListener(eventHandle) { | ||
var target = eventHandle.target; | ||
// There can be a race condition where the target may no longer exist when | ||
// this function is called, e.g. when a React component is unmounting. | ||
// Guarding against this prevents the following error: | ||
// | ||
// Cannot read property 'removeEventListener' of undefined | ||
if (target) { | ||
target[EVENT_HANDLERS_KEY]['delete'](eventHandle); | ||
} | ||
// Deprecated | ||
function removeEventListener(unsubscribeFn) { | ||
unsubscribeFn(); | ||
} |
@@ -31,8 +31,7 @@ Object.defineProperty(exports, "__esModule", { | ||
this.events[key] = { | ||
size: 0, | ||
index: 0, | ||
handlers: {}, | ||
handlers: [], | ||
handleEvent: undefined | ||
}; | ||
} | ||
return this.events[key]; | ||
@@ -50,4 +49,3 @@ } | ||
Object.keys(handlers).forEach(function (index) { | ||
var handler = handlers[index]; | ||
handlers.forEach(function (handler) { | ||
if (handler) { | ||
@@ -69,6 +67,8 @@ // We need to check for presence here because a handler function may | ||
function add(eventName, listener, options) { | ||
var _this = this; | ||
// options has already been normalized at this point. | ||
var eventHandlers = this.getEventHandlers(eventName, options); | ||
if (eventHandlers.size === 0) { | ||
if (eventHandlers.handlers.length === 0) { | ||
eventHandlers.handleEvent = this.handleEvent.bind(this, eventName, options); | ||
@@ -79,45 +79,39 @@ | ||
eventHandlers.size += 1; | ||
eventHandlers.index += 1; | ||
eventHandlers.handlers[eventHandlers.index] = listener; | ||
eventHandlers.handlers.push(listener); | ||
return { | ||
target: this.target, | ||
eventName: eventName, | ||
options: options, | ||
index: eventHandlers.index | ||
}; | ||
} | ||
var isSubscribed = true; | ||
var unsubscribe = function () { | ||
function unsubscribe() { | ||
if (!isSubscribed) { | ||
return; | ||
} | ||
return add; | ||
}() | ||
}, { | ||
key: 'delete', | ||
value: function () { | ||
function _delete(_ref) { | ||
var eventName = _ref.eventName, | ||
index = _ref.index, | ||
options = _ref.options; | ||
isSubscribed = false; | ||
// options has already been normalized at this point. | ||
var eventHandlers = this.getEventHandlers(eventName, options); | ||
var index = eventHandlers.handlers.indexOf(listener); | ||
eventHandlers.handlers.splice(index, 1); | ||
if (eventHandlers.size === 0) { | ||
// There are no matching event handlers, so no work to be done here. | ||
return; | ||
} | ||
if (eventHandlers.handlers.length === 0) { | ||
// All event handlers have been removed, so we want to remove the event | ||
// listener from the target node. | ||
if (eventHandlers.handlers[index]) { | ||
delete eventHandlers.handlers[index]; | ||
eventHandlers.size -= 1; | ||
} | ||
if (_this.target) { | ||
// There can be a race condition where the target may no longer exist | ||
// when this function is called, e.g. when a React component is | ||
// unmounting. Guarding against this prevents the following error: | ||
// | ||
// Cannot read property 'removeEventListener' of undefined | ||
_this.target.removeEventListener(eventName, eventHandlers.handleEvent, options); | ||
} | ||
if (eventHandlers.size === 0) { | ||
this.target.removeEventListener(eventName, eventHandlers.handleEvent, options); | ||
eventHandlers.handleEvent = undefined; | ||
} | ||
} | ||
eventHandlers.handleEvent = undefined; | ||
} | ||
return unsubscribe; | ||
}(); | ||
return unsubscribe; | ||
} | ||
return _delete; | ||
return add; | ||
}() | ||
@@ -124,0 +118,0 @@ }]); |
{ | ||
"name": "consolidated-events", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "Manage multiple event handlers using few event listeners", | ||
@@ -39,14 +39,15 @@ "main": "lib/index.js", | ||
"devDependencies": { | ||
"babel-cli": "^6.18.0", | ||
"babel-core": "^6.18.2", | ||
"babel-jest": "^17.0.0", | ||
"babel-preset-airbnb": "^2.1.1", | ||
"eslint": "^3.9.1", | ||
"eslint-config-airbnb-base": "^10.0.1", | ||
"eslint-plugin-import": "^2.2.0", | ||
"babel-cli": "^6.22.2", | ||
"babel-core": "^6.22.1", | ||
"babel-jest": "^20.0.0", | ||
"babel-preset-airbnb": "^2.2.3", | ||
"eslint": "^3.15.0", | ||
"eslint-config-airbnb-base": "^11.1.0", | ||
"eslint-plugin-import": "^2.3.0", | ||
"in-publish": "^2.0.0", | ||
"jest": "^17.0.0", | ||
"rimraf": "^2.5.4", | ||
"jest": "^20.0.0", | ||
"jest-wrap": "^1.0.0", | ||
"rimraf": "^2.6.1", | ||
"safe-publish-latest": "^1.1.1" | ||
} | ||
} |
@@ -17,5 +17,5 @@ # consolidated-events <sup>[![Version Badge][npm-version-svg]][package-url]</sup> | ||
```js | ||
import { addEventListener, removeEventListener } from 'consolidated-events'; | ||
import { addEventListener } from 'consolidated-events'; | ||
const handle = addEventListener( | ||
const removeEventListener = addEventListener( | ||
window, | ||
@@ -22,0 +22,0 @@ 'scroll', |
@@ -10,2 +10,6 @@ import canUseDOM from './canUseDOM'; | ||
if (!window.addEventListener || !window.removeEventListener || !Object.defineProperty) { | ||
return false; | ||
} | ||
let supportsPassiveOption = false; | ||
@@ -12,0 +16,0 @@ try { |
@@ -16,13 +16,5 @@ import normalizeEventOptions from './normalizeEventOptions'; | ||
export function removeEventListener(eventHandle) { | ||
const { target } = eventHandle; | ||
// There can be a race condition where the target may no longer exist when | ||
// this function is called, e.g. when a React component is unmounting. | ||
// Guarding against this prevents the following error: | ||
// | ||
// Cannot read property 'removeEventListener' of undefined | ||
if (target) { | ||
target[EVENT_HANDLERS_KEY].delete(eventHandle); | ||
} | ||
// Deprecated | ||
export function removeEventListener(unsubscribeFn) { | ||
unsubscribeFn(); | ||
} |
@@ -14,8 +14,7 @@ import eventOptionsKey from './eventOptionsKey'; | ||
this.events[key] = { | ||
size: 0, | ||
index: 0, | ||
handlers: {}, | ||
handlers: [], | ||
handleEvent: undefined, | ||
}; | ||
} | ||
return this.events[key]; | ||
@@ -26,4 +25,3 @@ } | ||
const { handlers } = this.getEventHandlers(eventName, options); | ||
Object.keys(handlers).forEach((index) => { | ||
const handler = handlers[index]; | ||
handlers.forEach((handler) => { | ||
if (handler) { | ||
@@ -43,3 +41,3 @@ // We need to check for presence here because a handler function may | ||
if (eventHandlers.size === 0) { | ||
if (eventHandlers.handlers.length === 0) { | ||
eventHandlers.handleEvent = this.handleEvent.bind(this, eventName, options); | ||
@@ -54,38 +52,37 @@ | ||
eventHandlers.size += 1; | ||
eventHandlers.index += 1; | ||
eventHandlers.handlers[eventHandlers.index] = listener; | ||
eventHandlers.handlers.push(listener); | ||
return { | ||
target: this.target, | ||
eventName, | ||
options, | ||
index: eventHandlers.index, | ||
}; | ||
} | ||
let isSubscribed = true; | ||
const unsubscribe = () => { | ||
if (!isSubscribed) { | ||
return; | ||
} | ||
delete({ eventName, index, options }) { | ||
// options has already been normalized at this point. | ||
const eventHandlers = this.getEventHandlers(eventName, options); | ||
isSubscribed = false; | ||
if (eventHandlers.size === 0) { | ||
// There are no matching event handlers, so no work to be done here. | ||
return; | ||
} | ||
const index = eventHandlers.handlers.indexOf(listener); | ||
eventHandlers.handlers.splice(index, 1); | ||
if (eventHandlers.handlers[index]) { | ||
delete eventHandlers.handlers[index]; | ||
eventHandlers.size -= 1; | ||
} | ||
if (eventHandlers.handlers.length === 0) { | ||
// All event handlers have been removed, so we want to remove the event | ||
// listener from the target node. | ||
if (eventHandlers.size === 0) { | ||
this.target.removeEventListener( | ||
eventName, | ||
eventHandlers.handleEvent, | ||
options, | ||
); | ||
if (this.target) { | ||
// There can be a race condition where the target may no longer exist | ||
// when this function is called, e.g. when a React component is | ||
// unmounting. Guarding against this prevents the following error: | ||
// | ||
// Cannot read property 'removeEventListener' of undefined | ||
this.target.removeEventListener( | ||
eventName, | ||
eventHandlers.handleEvent, | ||
options, | ||
); | ||
} | ||
eventHandlers.handleEvent = undefined; | ||
} | ||
eventHandlers.handleEvent = undefined; | ||
} | ||
}; | ||
return unsubscribe; | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
34922
27
743
12