package.js.lib.event.js Maven / Gradle / Ivy
const listenerRegistry = new WeakMap();
const {addEventListener, removeEventListener} = EventTarget.prototype;
// Register event listeners to a key object
// listeners: array of listener definitions;
// - each definition must be a flat array of event target and the arguments
// used to call addEventListener() on the target
export function registerListeners(keyObj, listeners) {
let registered = listenerRegistry.get(keyObj);
if (!registered) {
registered = [];
listenerRegistry.set(keyObj, registered);
}
listeners.forEach((listener) => {
addEventListener.call(...listener);
registered.push(listener);
});
}
export function unregisterListeners(keyObj) {
let listeners = listenerRegistry.get(keyObj);
if (!listeners) {
return;
}
listeners.forEach((listener) => {
removeEventListener.call(...listener);
});
listenerRegistry.delete(keyObj);
}
// Event.composedPath() polyfill for Edge
// based on https://gist.github.com/kleinfreund/e9787d73776c0e3750dcfcdc89f100ec
if (!Event.prototype.composedPath) {
const getComposedPath = (node, path = []) => {
path.push(node);
let parent;
if (node.parentNode) {
parent = node.parentNode;
} else if (node.host) { // ShadowRoot
parent = node.host;
} else if (node.defaultView) { // Document
parent = node.defaultView;
}
return parent ? getComposedPath(parent, path) : path;
};
Event.prototype.composedPath = function () {
return getComposedPath(this.target);
};
}
function findFromPath(path, criteria, currentTarget, index = 0) {
const el = path[index];
if (criteria(el)) {
return el;
} else if (el === currentTarget || !el.parentElement) {
// stop when reaching currentTarget or
return;
}
return findFromPath(path, criteria, currentTarget, index + 1);
}
// Search for the actual target of a delegated event
export function findElementInEventPath(ev, selector) {
const criteria = typeof selector === 'function' ? selector : el => el.matches(selector);
return findFromPath(ev.composedPath(), criteria, ev.currentTarget);
}