mirror of
https://github.com/aelve/guide.git
synced 2024-11-22 03:12:58 +03:00
Search shortcut
This commit is contained in:
parent
082bfb01a6
commit
af29bcf79d
@ -2,6 +2,7 @@
|
||||
<v-form
|
||||
class="search-bar"
|
||||
@keydown.enter.native.prevent="processSearchQuery"
|
||||
@keydown.esc.native.prevent="blur"
|
||||
>
|
||||
<v-text-field
|
||||
solo
|
||||
@ -28,6 +29,12 @@
|
||||
v-show="searchQuery"
|
||||
@click="clear"
|
||||
>$vuetify.icons.times</v-icon>
|
||||
<span
|
||||
slot="append"
|
||||
class="search-bar__input__shortcut-tip"
|
||||
v-show="!isFocused"
|
||||
@click="clear"
|
||||
>/</span>
|
||||
</v-text-field>
|
||||
</v-form>
|
||||
</template>
|
||||
@ -35,13 +42,42 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import Component from 'vue-class-component'
|
||||
|
||||
import isEventTypingOrDialog from 'client/helpers/isEventTypingOrDialog'
|
||||
@Component
|
||||
export default class SearchBar extends Vue {
|
||||
|
||||
shortcutListener
|
||||
isFocused = false
|
||||
searchQuery = this.$store.state.wiki.searchQuery
|
||||
|
||||
get inputIconsColor () {
|
||||
return this.isFocused ? '#717171' : 'rgba(255, 255, 255, 0.7)'
|
||||
}
|
||||
|
||||
mounted () {
|
||||
this.addShortcutListener()
|
||||
}
|
||||
|
||||
beforeDestroy () {
|
||||
this.removeShortcutListener()
|
||||
}
|
||||
|
||||
addShortcutListener () {
|
||||
this.shortcutListener = document.addEventListener('keydown', event => {
|
||||
const { keyCode } = event
|
||||
const slashButtonCode = 191
|
||||
if (keyCode !== slashButtonCode || this.isFocused || isEventTypingOrDialog(event)) {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
this.focus()
|
||||
})
|
||||
}
|
||||
|
||||
removeShortcutListener () {
|
||||
document.removeEventListener('keydown', this.shortcutListener)
|
||||
}
|
||||
|
||||
processSearchQuery () {
|
||||
const searchResultsRouteName = 'SearchResults'
|
||||
const isSearchCurrentRoute = this.$route.name === searchResultsRouteName
|
||||
@ -53,10 +89,6 @@ export default class SearchBar extends Vue {
|
||||
this.$router.push({ name: searchResultsRouteName, query: { query: this.searchQuery } })
|
||||
}
|
||||
|
||||
get inputIconsColor () {
|
||||
return this.isFocused ? '#717171' : 'rgba(255, 255, 255, 0.7)'
|
||||
}
|
||||
|
||||
clear () {
|
||||
this.searchQuery = ''
|
||||
}
|
||||
@ -64,6 +96,12 @@ export default class SearchBar extends Vue {
|
||||
focus () {
|
||||
this.$refs.input.focus()
|
||||
}
|
||||
|
||||
blur () {
|
||||
if (this.isFocused) {
|
||||
this.$refs.input.blur()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -96,9 +134,22 @@ export default class SearchBar extends Vue {
|
||||
.search-bar__input__clear-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
.search-bar__input__shortcut-tip {
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
font-size: 0.6rem;
|
||||
border: rgba(255, 255, 255, 0.3) solid 1px;
|
||||
border-radius: 3px;
|
||||
line-height: 0.3rem;
|
||||
padding: 0.4rem;
|
||||
}
|
||||
@media screen and (min-width: 780px) {
|
||||
.search-bar__input__clear-btn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 780px) {
|
||||
.search-bar__input__shortcut-tip {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
10
front/client/helpers/isEventTypingOrDialog.ts
Normal file
10
front/client/helpers/isEventTypingOrDialog.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export default function (event) {
|
||||
const { target } = event
|
||||
const dialogSelector = '.v-dialog__content'
|
||||
const isDialog = target.classList.contains(dialogSelector) || target.closest(dialogSelector)
|
||||
const nodeName = target.nodeName.toLowerCase()
|
||||
const typingElements = ['input', 'textarea']
|
||||
const isTypingElement = typingElements.includes(nodeName)
|
||||
|
||||
return isDialog || isTypingElement
|
||||
}
|
Loading…
Reference in New Issue
Block a user