2023-08-01 16:41:58 +08:00
|
|
|
// Use this to register outside-click directive on a Vue component
|
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
// eg v-click-outside="{handler: 'handlerToTrigger', exclude: [refs to ignore on click (eg 'searchInput', 'searchInputBtn')]}"
|
|
|
|
// eslint-enable-next-line max-len
|
|
|
|
|
|
|
|
export default {
|
|
|
|
bind(el, binding, vnode) {
|
2023-10-12 21:27:36 +08:00
|
|
|
el._vueClickOutside_ = (e) => {
|
2023-08-01 16:41:58 +08:00
|
|
|
e.stopPropagation();
|
|
|
|
|
|
|
|
let clickedOnExcludedEl = false;
|
2023-10-12 21:27:36 +08:00
|
|
|
const { exclude } = binding.value;
|
2023-08-01 16:41:58 +08:00
|
|
|
exclude.forEach(refName => {
|
|
|
|
if (!clickedOnExcludedEl) {
|
|
|
|
const excludedEl = vnode.context.$refs[refName];
|
2023-10-13 22:12:01 +08:00
|
|
|
if (!excludedEl) return;
|
|
|
|
|
|
|
|
clickedOnExcludedEl = (excludedEl._isVue ? excludedEl.$el : excludedEl).contains(e.target);
|
2023-08-01 16:41:58 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!el.contains(e.target) && !clickedOnExcludedEl) {
|
2023-10-12 21:27:36 +08:00
|
|
|
const { handler } = binding.value;
|
2023-08-01 16:41:58 +08:00
|
|
|
vnode.context[handler]();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-10-12 21:27:36 +08:00
|
|
|
document.addEventListener('click', el._vueClickOutside_);
|
|
|
|
document.addEventListener('touchstart', el._vueClickOutside_);
|
2023-08-01 16:41:58 +08:00
|
|
|
},
|
2023-10-12 21:27:36 +08:00
|
|
|
unbind(el) {
|
|
|
|
document.removeEventListener('click', el._vueClickOutside_);
|
|
|
|
document.removeEventListener('touchstart', el._vueClickOutside_);
|
|
|
|
el._vueClickOutside_ = null;
|
2023-08-01 16:41:58 +08:00
|
|
|
}
|
|
|
|
};
|