diff --git a/app/javascript/packs/vue/directives/outside_click.js b/app/javascript/packs/vue/directives/outside_click.js new file mode 100644 index 000000000..fc85316f6 --- /dev/null +++ b/app/javascript/packs/vue/directives/outside_click.js @@ -0,0 +1,35 @@ +// 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 + +let handleOutsideClick; + +export default { + bind(el, binding, vnode) { + const { handler, exclude } = binding.value; + + handleOutsideClick = (e) => { + e.stopPropagation(); + + let clickedOnExcludedEl = false; + exclude.forEach(refName => { + if (!clickedOnExcludedEl) { + const excludedEl = vnode.context.$refs[refName]; + clickedOnExcludedEl = excludedEl?.contains(e.target); + } + }); + + if (!el.contains(e.target) && !clickedOnExcludedEl) { + vnode.context[handler](); + } + }; + + document.addEventListener('click', handleOutsideClick); + document.addEventListener('touchstart', handleOutsideClick); + }, + unbind() { + document.removeEventListener('click', handleOutsideClick); + document.removeEventListener('touchstart', handleOutsideClick); + } +}; diff --git a/app/javascript/packs/vue/repository_search.js b/app/javascript/packs/vue/repository_search.js index 14eb2a225..698ea4426 100644 --- a/app/javascript/packs/vue/repository_search.js +++ b/app/javascript/packs/vue/repository_search.js @@ -1,9 +1,11 @@ import TurbolinksAdapter from 'vue-turbolinks'; import Vue from 'vue/dist/vue.esm'; import RepositorySearchContainer from '../../vue/repository_search/container.vue'; +import outsideClick from './directives/outside_click'; Vue.use(TurbolinksAdapter); Vue.prototype.i18n = window.I18n; +Vue.directive('click-outside', outsideClick); window.initRepositorySearch = () => { window.RepositorySearchComponent = new Vue({ diff --git a/app/javascript/vue/repository_search/container.vue b/app/javascript/vue/repository_search/container.vue index 29f5858f9..64745dc68 100644 --- a/app/javascript/vue/repository_search/container.vue +++ b/app/javascript/vue/repository_search/container.vue @@ -1,6 +1,9 @@