mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-03-09 06:04:46 +08:00
Fix issue when toggling repository items search fields [SCI-8874] (#5855)
* Fix issue when toggling repository items search fields [SCI-8874] * Refactor outside click directive and make it available for all components [SCI-8874]
This commit is contained in:
parent
556c1de182
commit
2680b317e5
3 changed files with 50 additions and 8 deletions
35
app/javascript/packs/vue/directives/outside_click.js
Normal file
35
app/javascript/packs/vue/directives/outside_click.js
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,9 +1,11 @@
|
||||||
import TurbolinksAdapter from 'vue-turbolinks';
|
import TurbolinksAdapter from 'vue-turbolinks';
|
||||||
import Vue from 'vue/dist/vue.esm';
|
import Vue from 'vue/dist/vue.esm';
|
||||||
import RepositorySearchContainer from '../../vue/repository_search/container.vue';
|
import RepositorySearchContainer from '../../vue/repository_search/container.vue';
|
||||||
|
import outsideClick from './directives/outside_click';
|
||||||
|
|
||||||
Vue.use(TurbolinksAdapter);
|
Vue.use(TurbolinksAdapter);
|
||||||
Vue.prototype.i18n = window.I18n;
|
Vue.prototype.i18n = window.I18n;
|
||||||
|
Vue.directive('click-outside', outsideClick);
|
||||||
|
|
||||||
window.initRepositorySearch = () => {
|
window.initRepositorySearch = () => {
|
||||||
window.RepositorySearchComponent = new Vue({
|
window.RepositorySearchComponent = new Vue({
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center mr-3 flex-nowrap">
|
<div
|
||||||
<button v-if="!searchOpened" class="btn btn-light btn-lg btn-black icon-btn" :title="i18n.t('repositories.show.search_button_tooltip')" @click="openSearch">
|
class="flex items-center mr-3 flex-nowrap relative"
|
||||||
|
v-click-outside="{handler: 'closeSearchInputs', exclude: ['searchInput', 'searchInputBtn', 'barcodeSearchInput', 'barcodeSearchInputBtn']}"
|
||||||
|
>
|
||||||
|
<button :class="{hidden: searchOpened}" ref='searchInputBtn' class="btn btn-light btn-lg btn-black icon-btn" :title="i18n.t('repositories.show.search_button_tooltip')" @click="openSearch">
|
||||||
<i class="sn-icon sn-icon-search"></i>
|
<i class="sn-icon sn-icon-search"></i>
|
||||||
</button>
|
</button>
|
||||||
<div v-if="searchOpened || barcodeSearchOpened" class="w-52 flex">
|
<div v-if="searchOpened || barcodeSearchOpened" class="w-52 flex">
|
||||||
|
@ -11,7 +14,6 @@
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="i18n.t('repositories.show.filter_inventory_items')"
|
:placeholder="i18n.t('repositories.show.filter_inventory_items')"
|
||||||
@keyup="setValue"
|
@keyup="setValue"
|
||||||
@blur="closeSearch"
|
|
||||||
/>
|
/>
|
||||||
<i class="sn-icon sn-icon-search !mr-2.5"></i>
|
<i class="sn-icon sn-icon-search !mr-2.5"></i>
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,13 +23,12 @@
|
||||||
class="sci-input-field"
|
class="sci-input-field"
|
||||||
type="text"
|
type="text"
|
||||||
:placeholder="i18n.t('repositories.show.filter_inventory_items_with_ean')"
|
:placeholder="i18n.t('repositories.show.filter_inventory_items_with_ean')"
|
||||||
@change="setBarcodeValue"
|
@keyup="setBarcodeValue"
|
||||||
@blur="closeBarcodeSearch"
|
|
||||||
/>
|
/>
|
||||||
<i class='sn-icon sn-icon-barcode barcode-scanner !mr-2.5'></i>
|
<i class='sn-icon sn-icon-barcode barcode-scanner !mr-2.5'></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button v-if="!barcodeSearchOpened" class="btn btn-light btn-lg btn-black icon-btn ml-2" :title="i18n.t('repositories.show.ean_search_button_tooltip')" @click="openBarcodeSearch">
|
<button :class="{hidden: barcodeSearchOpened}" ref='barcodeSearchInputBtn' class="btn btn-light btn-lg btn-black icon-btn ml-2" :title="i18n.t('repositories.show.ean_search_button_tooltip')" @click="openBarcodeSearch">
|
||||||
<i class='sn-icon sn-icon-barcode barcode-scanner'></i>
|
<i class='sn-icon sn-icon-barcode barcode-scanner'></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,7 +67,7 @@ export default {
|
||||||
},
|
},
|
||||||
openBarcodeSearch() {
|
openBarcodeSearch() {
|
||||||
this.clearValues();
|
this.clearValues();
|
||||||
this.closeSearch();
|
this.searchOpened = false;
|
||||||
this.barcodeSearchOpened = true;
|
this.barcodeSearchOpened = true;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.barcodeSearchInput.focus();
|
this.$refs.barcodeSearchInput.focus();
|
||||||
|
@ -74,7 +75,7 @@ export default {
|
||||||
},
|
},
|
||||||
openSearch() {
|
openSearch() {
|
||||||
this.clearValues();
|
this.clearValues();
|
||||||
this.closeBarcodeSearch();
|
this.barcodeSearchOpened = false;
|
||||||
this.searchOpened = true;
|
this.searchOpened = true;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.searchInput.focus();
|
this.$refs.searchInput.focus();
|
||||||
|
@ -103,6 +104,10 @@ export default {
|
||||||
this.barcodeValue = '';
|
this.barcodeValue = '';
|
||||||
if (this.$refs.searchInput) this.$refs.searchInput.value = '';
|
if (this.$refs.searchInput) this.$refs.searchInput.value = '';
|
||||||
if (this.$refs.barcodeSearchInput) this.$refs.barcodeSearchInput.value = '';
|
if (this.$refs.barcodeSearchInput) this.$refs.barcodeSearchInput.value = '';
|
||||||
|
},
|
||||||
|
closeSearchInputs() {
|
||||||
|
this.closeSearch();
|
||||||
|
this.closeBarcodeSearch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue