vanillajs-datepicker
Version:
A vanilla JavaScript remake of bootstrap-datepicker for Bulma and other CSS frameworks
72 lines (64 loc) • 2.16 kB
JavaScript
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) {
const [node, ...rest] = path;
if (criteria(node)) {
return node;
}
if (node === currentTarget || node.tagName === 'HTML' || rest.length === 0) {
// stop when reaching currentTarget or <html>
return;
}
return findFromPath(rest, criteria, currentTarget);
}
// Search for the actual target of a delegated event
export function findElementInEventPath(ev, selector) {
const criteria = typeof selector === 'function'
? selector
: el => el instanceof Element && el.matches(selector);
return findFromPath(ev.composedPath(), criteria, ev.currentTarget);
}