From ffdc566b8b50b8d77f80e69be7232d85204158dd Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 22 Sep 2021 17:37:27 +0200 Subject: [PATCH 1/2] [WIP] Completer.js: Prevent completion query spamming --- asset/css/search-base.less | 3 ++- asset/js/widget/Completer.js | 31 +++++++++++++++++++++++++++++++ src/Control/SearchBar.php | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/asset/css/search-base.less b/asset/css/search-base.less index 60229ff3..c3488560 100644 --- a/asset/css/search-base.less +++ b/asset/css/search-base.less @@ -33,7 +33,8 @@ font-size: 80%; } - .failure-message { + .failure-message, + .progress-indicator { font-weight: bold; em { diff --git a/asset/js/widget/Completer.js b/asset/js/widget/Completer.js index 81f12262..274c18d4 100644 --- a/asset/js/widget/Completer.js +++ b/asset/js/widget/Completer.js @@ -12,6 +12,7 @@ define(["../notjQuery"], function ($) { this.completedValue = null; this.completedData = null; this._termSuggestions = null; + this.last_response_times = []; } get termSuggestions() { @@ -177,6 +178,19 @@ define(["../notjQuery"], function ($) { } requestCompletion(input, data, trigger = 'user') { + let showProgress = false; + if (this.last_response_times.length === 3) { + let avgResponseTime = this.last_response_times.reduce((a, b) => a + b) + / this.last_response_times.length; + if (avgResponseTime > 1000) { + if (this.activeSuggestion !== null) { + return; + } + + showProgress = true; + } + } + this.abort(); this.nextSuggestion = setTimeout(() => { @@ -194,8 +208,14 @@ define(["../notjQuery"], function ($) { } } + let now = Date.now(); req.addEventListener('loadend', () => { + let hide = false; if (req.readyState > 0) { + if (this.last_response_times.push(Date.now() - now) > 3) { + this.last_response_times.shift(); + } + if (req.responseText) { let suggestions = this.renderSuggestions(req.responseText); if (trigger === 'script') { @@ -222,6 +242,17 @@ define(["../notjQuery"], function ($) { req.send(JSON.stringify(data)); + if (showProgress) { + this.showSuggestions(this.renderSuggestions(` + + `), input); + } + this.activeSuggestion = req; }, 200); } diff --git a/src/Control/SearchBar.php b/src/Control/SearchBar.php index 9a47bf9f..79654405 100644 --- a/src/Control/SearchBar.php +++ b/src/Control/SearchBar.php @@ -289,6 +289,7 @@ protected function assemble() 'data-incomplete-group' => t('Please close or remove this group.'), 'data-choose-template' => t('Please type one of: %s', '..'), 'data-choose-column' => t('Please enter a valid column.'), + 'data-complete-active' => t('Searching...'), 'validators' => [ new CallbackValidator(function ($q, CallbackValidator $validator) { try { From 2fb600ec05b04235d289651b48a00d7aa15ea4ab Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 22 Sep 2021 17:38:25 +0200 Subject: [PATCH 2/2] Completer.js: Really close suggestions if there are none --- asset/js/widget/Completer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/asset/js/widget/Completer.js b/asset/js/widget/Completer.js index 274c18d4..9c17d053 100644 --- a/asset/js/widget/Completer.js +++ b/asset/js/widget/Completer.js @@ -232,12 +232,16 @@ define(["../notjQuery"], function ($) { this.showSuggestions(suggestions, input); } } else { - this.hideSuggestions(); + hide = true; } } this.activeSuggestion = null; this.nextSuggestion = null; + + if (hide) { + this.hideSuggestions(); + } }); req.send(JSON.stringify(data));