You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
47 lines
1.2 KiB
47 lines
1.2 KiB
const supportedMatchesName:
|
|
| 'matches'
|
|
| 'msMatchesSelector'
|
|
| 'webkitMatchesSelector' = (() => {
|
|
const base = 'matches' as const;
|
|
|
|
// Server side rendering
|
|
if (typeof document === 'undefined') {
|
|
return base;
|
|
}
|
|
|
|
// See https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
|
const candidates = [
|
|
base,
|
|
'msMatchesSelector' as const,
|
|
'webkitMatchesSelector' as const,
|
|
];
|
|
|
|
const value = candidates.find((name): boolean => name in Element.prototype);
|
|
|
|
return value || base;
|
|
})();
|
|
|
|
function closestPonyfill(el: Element | null, selector: string): null | Element {
|
|
if (el == null) {
|
|
return null;
|
|
}
|
|
|
|
// Element.prototype.matches is supported in ie11 with a different name
|
|
// https://caniuse.com/#feat=matchesselector
|
|
if (el[supportedMatchesName as 'matches'](selector)) {
|
|
return el;
|
|
}
|
|
|
|
// recursively look up the tree
|
|
return closestPonyfill(el.parentElement, selector);
|
|
}
|
|
|
|
export default function closest(el: Element, selector: string): Element | null {
|
|
// Using native closest for maximum speed where we can
|
|
if (el.closest) {
|
|
return el.closest(selector);
|
|
}
|
|
// ie11: damn you!
|
|
return closestPonyfill(el, selector);
|
|
}
|