UX: Delay search query update until user has finished typing #1995

This commit is contained in:
Michael Mayer 2022-03-24 11:29:40 +01:00
parent 16caeef272
commit 426170a392
6 changed files with 98 additions and 60 deletions

View file

@ -1,21 +1,22 @@
<template>
<v-form ref="form" lazy-validation
dense autocomplete="off" class="p-photo-toolbar" accept-charset="UTF-8"
@submit.prevent="filterChange">
@submit.prevent="updateQuery">
<v-toolbar flat :dense="$vuetify.breakpoint.smAndDown" class="page-toolbar" color="secondary">
<v-text-field v-model.lazy.trim="filter.q"
<v-text-field :value="filter.q"
class="input-search background-inherit elevation-0"
solo hide-details clearable overflow single-line validate-on-blur
autocorrect="off"
autocapitalize="none"
browser-autocomplete="off"
solo hide-details clearable overflow single-line
:label="$gettext('Search')"
prepend-inner-icon="search"
color="secondary-dark"
@input="onChangeQuery"
@change="updateQuery"
@blur="updateQuery"
@keyup.enter.native="updateQuery"
@click:clear="clearQuery"
@blur="filterChange"
@change="filterChange"
@keyup.enter.native="filterChange"
></v-text-field>
<v-btn icon class="hidden-xs-only action-reload" :title="$gettext('Reload')" @click.stop="refresh">
@ -177,6 +178,7 @@ export default {
isFullScreen: !!document.fullscreenElement,
config: this.$config.values,
searchExpanded: false,
q: this.filter.q ? this.filter.q : "",
all: {
countries: [{ID: "", Name: this.$gettext("All Countries")}],
cameras: [{ID: 0, Name: this.$gettext("All Cameras")}],
@ -239,8 +241,15 @@ export default {
this.settings.view = name;
this.filterChange();
},
onChangeQuery(val) {
this.q = String(val);
},
clearQuery() {
this.filter.q = '';
this.q = '';
this.updateQuery();
},
updateQuery() {
this.filter.q = this.q.trim();
this.filterChange();
},
showUpload() {

View file

@ -5,9 +5,8 @@
<v-form ref="form" class="p-albums-search" lazy-validation dense @submit.prevent="updateQuery">
<v-toolbar flat :dense="$vuetify.breakpoint.smAndDown" class="page-toolbar" color="secondary">
<v-text-field id="search"
v-model.lazy.trim="filter.q"
solo hide-details clearable overflow single-line
<v-text-field :value="filter.q"
solo hide-details clearable overflow single-line validate-on-blur
class="input-search background-inherit elevation-0"
:label="$gettext('Search')"
browser-autocomplete="off"
@ -15,10 +14,11 @@
autocapitalize="none"
prepend-inner-icon="search"
color="secondary-dark"
@click:clear="clearQuery"
@blur="updateQuery"
@input="onChangeQuery"
@change="updateQuery"
@blur="updateQuery"
@keyup.enter.native="updateQuery"
@click:clear="clearQuery"
></v-text-field>
<v-overflow-btn v-model="filter.category"
@ -254,6 +254,7 @@ export default {
page: 0,
selection: [],
settings: settings,
q: q,
filter: filter,
lastFilter: {},
routeName: routeName,
@ -285,10 +286,12 @@ export default {
'$route'() {
const query = this.$route.query;
this.filter.q = query["q"] ? query["q"] : "";
this.filter.category = query["category"] ? query["category"] : "";
this.lastFilter = {};
this.routeName = this.$route.name;
this.lastFilter = {};
this.q = query["q"] ? query["q"] : "";
this.filter.q = this.q;
this.filter.category = query["category"] ? query["category"] : "";
this.search();
}
},
@ -432,10 +435,6 @@ export default {
}
}
},
clearQuery() {
this.filter.q = '';
this.search();
},
loadMore() {
if (this.scrollDisabled) return;
@ -485,7 +484,16 @@ export default {
this.listen = true;
});
},
onChangeQuery(val) {
this.q = String(val);
},
clearQuery() {
this.q = '';
this.updateQuery();
},
updateQuery() {
this.filter.q = this.q.trim();
if (this.loading) return;
const query = {

View file

@ -3,22 +3,22 @@
:infinite-scroll-disabled="scrollDisabled" :infinite-scroll-distance="1200"
:infinite-scroll-listen-for-event="'scrollRefresh'">
<v-form ref="form" class="p-labels-search" lazy-validation dense @submit.prevent="updateQuery">
<v-form ref="form" class="p-labels-search" lazy-validation dense @submit.stop.prevent>
<v-toolbar flat :dense="$vuetify.breakpoint.smAndDown" class="page-toolbar" color="secondary">
<v-text-field id="search"
v-model.lazy.trim="filter.q"
<v-text-field :value="filter.q"
solo hide-details clearable overflow single-line validate-on-blur
class="input-search background-inherit elevation-0"
solo hide-details clearable overflow
:label="$gettext('Search')"
prepend-inner-icon="search"
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
color="secondary-dark"
@click:clear="clearQuery"
@blur="updateQuery"
@input="onChangeQuery"
@change="updateQuery"
@blur="updateQuery"
@keyup.enter.native="updateQuery"
@click:clear="clearQuery"
></v-text-field>
<v-btn icon class="action-reload" :title="$gettext('Reload')" @click.stop="refresh">
@ -169,7 +169,7 @@ export default {
const routeName = this.$route.name;
const q = query['q'] ? query['q'] : '';
const all = query['all'] ? query['all'] : '';
const filter = {q: q, all: all};
const filter = {"q": String(q), all: String(all)};
const settings = {};
return {
@ -186,6 +186,7 @@ export default {
page: 0,
selection: [],
settings: settings,
q: q,
filter: filter,
lastFilter: {},
routeName: routeName,
@ -198,12 +199,14 @@ export default {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.filter.all = query['all'] ? query['all'] : '';
this.lastFilter = {};
this.routeName = this.$route.name;
this.lastFilter = {};
this.q = query['q'] ? query['q'] : '';
this.filter.q = this.q;
this.filter.all = query['all'] ? query['all'] : '';
this.search();
}
},
},
created() {
this.search();
@ -324,10 +327,6 @@ export default {
this.filter.all = "";
this.updateQuery();
},
clearQuery() {
this.filter.q = '';
this.updateQuery();
},
addSelection(uid) {
const pos = this.selection.indexOf(uid);
@ -417,7 +416,16 @@ export default {
this.listen = true;
});
},
onChangeQuery(val) {
this.q = String(val);
},
clearQuery() {
this.q = '';
this.updateQuery();
},
updateQuery() {
this.filter.q = this.q.trim();
if (this.loading) return;
const query = {

View file

@ -2,19 +2,20 @@
<div v-infinite-scroll="loadMore" class="p-page p-page-errors" :infinite-scroll-disabled="scrollDisabled"
:infinite-scroll-distance="1200" :infinite-scroll-listen-for-event="'scrollRefresh'">
<v-toolbar flat :dense="$vuetify.breakpoint.smAndDown" class="page-toolbar" color="secondary">
<v-text-field v-model.lazy.trim="filter.q"
<v-text-field :value="filter.q"
solo hide-details clearable overflow single-line validate-on-blur
class="input-search background-inherit elevation-0"
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
solo hide-details clearable overflow
:label="$gettext('Search')"
prepend-inner-icon="search"
color="secondary-dark"
@click:clear="clearQuery"
@blur="updateQuery"
@input="onChangeQuery"
@change="updateQuery"
@blur="updateQuery"
@keyup.enter.native="updateQuery"
@click:clear="clearQuery"
></v-text-field>
<v-spacer></v-spacer>
<v-btn icon class="action-reload" :title="$gettext('Reload')" @click.stop="reload">
@ -104,6 +105,7 @@ export default {
dirty: false,
loading: false,
scrollDisabled: false,
q: q,
filter: {q},
batchSize: 100,
offset: 0,
@ -119,7 +121,10 @@ export default {
watch: {
'$route'() {
const query = this.$route.query;
this.filter.q = query['q'] ? query['q'] : '';
this.q = query['q'] ? query['q'] : '';
this.filter.q = this.q;
this.reload();
}
},
@ -127,7 +132,16 @@ export default {
this.loadMore();
},
methods: {
onChangeQuery(val) {
this.q = String(val);
},
clearQuery() {
this.q = '';
this.updateQuery();
},
updateQuery() {
this.filter.q = this.q.trim();
if (this.loading) return;
const query = {};
@ -146,10 +160,6 @@ export default {
this.$router.replace({query});
},
clearQuery() {
this.filter.q = "";
this.updateQuery();
},
showDetails(err) {
this.details.err = err;
this.details.show = true;

View file

@ -5,21 +5,20 @@
<v-form ref="form" class="p-people-search" lazy-validation dense @submit.prevent="updateQuery">
<v-toolbar dense flat class="page-toolbar" color="secondary-light pa-0">
<v-text-field id="search"
v-model.lazy.trim="filter.q"
<v-text-field :value="filter.q"
solo hide-details clearable overflow single-line validate-on-blur
class="input-search background-inherit elevation-0"
solo hide-details
:label="$gettext('Search')"
prepend-inner-icon="search"
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
clearable overflow
color="secondary-dark"
@click:clear="clearQuery"
@blur="updateQuery"
@input="onChangeQuery"
@change="updateQuery"
@blur="updateQuery"
@keyup.enter.native="updateQuery"
@click:clear="clearQuery"
></v-text-field>
<v-divider vertical></v-divider>
@ -213,6 +212,7 @@ export default {
page: 0,
selection: [],
settings: settings,
q: q,
filter: filter,
lastFilter: {},
routeName: routeName,
@ -244,10 +244,11 @@ export default {
const query = this.$route.query;
this.filter.q = query["q"] ? query["q"] : "";
this.routeName = this.$route.name;
this.q = query["q"] ? query["q"] : "";
this.filter.q = this.q;
this.filter.hidden = query["hidden"] ? query["hidden"] : "";
this.filter.order = this.sortOrder();
this.routeName = this.$route.name;
this.search();
}
@ -436,10 +437,6 @@ export default {
this.busy = false;
});
},
clearQuery() {
this.filter.q = '';
this.updateQuery();
},
addSelection(uid) {
const pos = this.selection.indexOf(uid);
@ -531,7 +528,16 @@ export default {
this.listen = true;
});
},
onChangeQuery(val) {
this.q = String(val);
},
clearQuery() {
this.q = '';
this.updateQuery();
},
updateQuery() {
this.filter.q = this.q.trim();
if (this.loading || !this.active) {
return;
}

View file

@ -4,14 +4,10 @@
<div class="map-control">
<div class="maplibregl-ctrl maplibregl-ctrl-group">
<v-text-field v-model.lazy.trim="filter.q"
solo hide-details clearable flat single-line validate-on-blur
class="pa-0 ma-0 input-search"
single-line
solo
flat
:label="$gettext('Search')"
prepend-inner-icon="search"
clearable
hide-details
browser-autocomplete="off"
autocorrect="off"
autocapitalize="none"
@ -56,6 +52,7 @@ export default {
'$route'() {
this.filter.q = this.query();
this.lastFilter = {};
this.search();
}
},