2024-01-29 09:26:07 +08:00

76 lines
2.4 KiB
JavaScript

import { on, off } from './delegate';
import { getEventTarget } from './utils';
const traps = {
mousemoveoutside: new WeakMap(),
clickoutside: new WeakMap()
};
function createTrapHandler(name, el, originalHandler) {
if (name === 'mousemoveoutside') {
const moveHandler = (e) => {
if (el.contains(getEventTarget(e)))
return;
originalHandler(e);
};
return {
mousemove: moveHandler,
touchstart: moveHandler
};
}
else if (name === 'clickoutside') {
let mouseDownOutside = false;
const downHandler = (e) => {
mouseDownOutside = !el.contains(getEventTarget(e));
};
const upHanlder = (e) => {
if (!mouseDownOutside)
return;
if (el.contains(getEventTarget(e)))
return;
originalHandler(e);
};
return {
mousedown: downHandler,
mouseup: upHanlder,
touchstart: downHandler,
touchend: upHanlder
};
}
console.error(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`[evtd/create-trap-handler]: name \`${name}\` is invalid. This could be a bug of evtd.`);
return {};
}
function ensureTrapHandlers(name, el, handler) {
const handlers = traps[name];
let elHandlers = handlers.get(el);
if (elHandlers === undefined) {
handlers.set(el, (elHandlers = new WeakMap()));
}
let trapHandler = elHandlers.get(handler);
if (trapHandler === undefined) {
elHandlers.set(handler, (trapHandler = createTrapHandler(name, el, handler)));
}
return trapHandler;
}
function trapOn(name, el, handler, options) {
if (name === 'mousemoveoutside' || name === 'clickoutside') {
const trapHandlers = ensureTrapHandlers(name, el, handler);
Object.keys(trapHandlers).forEach((key) => {
on(key, document, trapHandlers[key], options);
});
return true;
}
return false;
}
function trapOff(name, el, handler, options) {
if (name === 'mousemoveoutside' || name === 'clickoutside') {
const trapHandlers = ensureTrapHandlers(name, el, handler);
Object.keys(trapHandlers).forEach((key) => {
off(key, document, trapHandlers[key], options);
});
return true;
}
return false;
}
export { trapOff, trapOn };