]> BookStack Code Mirror - bookstack/blobdiff - resources/js/components/global-search.js
Removed parallel testing, updated predis
[bookstack] / resources / js / components / global-search.js
index 0af3ed375861884d919eb801c6f8717fa4096d7f..7bc8a1d45187f8f711f0362c15bcab42119996db 100644 (file)
@@ -1,42 +1,66 @@
-/**
- * @extends {Component}
- */
 import {htmlToDom} from "../services/dom";
+import {debounce} from "../services/util";
+import {KeyboardNavigationHandler} from "../services/keyboard-navigation";
+import {Component} from "./component";
 
-class GlobalSearch {
+/**
+ * Global (header) search box handling.
+ * Mainly to show live results preview.
+ */
+export class GlobalSearch extends Component {
 
     setup() {
         this.container = this.$el;
         this.input = this.$refs.input;
         this.suggestions = this.$refs.suggestions;
         this.suggestionResultsWrap = this.$refs.suggestionResults;
+        this.loadingWrap = this.$refs.loading;
+        this.button = this.$refs.button;
 
         this.setupListeners();
     }
 
     setupListeners() {
-        this.hideOnOuterEventListener = this.hideOnOuterEventListener.bind(this);
+        const updateSuggestionsDebounced = debounce(this.updateSuggestions.bind(this), 200, false);
 
+        // Handle search input changes
         this.input.addEventListener('input', () => {
             const value = this.input.value;
             if (value.length > 0) {
-                this.updateSuggestions(value);
+                this.loadingWrap.style.display = 'block';
+                this.suggestionResultsWrap.style.opacity = '0.5';
+                updateSuggestionsDebounced(value);
             }  else {
                 this.hideSuggestions();
             }
         });
+
+        // Allow double click to show auto-click suggestions
+        this.input.addEventListener('dblclick', () => {
+            this.input.setAttribute('autocomplete', 'on');
+            this.button.focus();
+            this.input.focus();
+        });
+
+        new KeyboardNavigationHandler(this.container, () => {
+            this.hideSuggestions();
+        });
     }
 
+    /**
+     * @param {String} search
+     */
     async updateSuggestions(search) {
-        const {data: results} = await window.$http.get('/ajax/search/entities', {term: search, count: 5});
-        const resultDom = htmlToDom(results);
-
-        const childrenToTrim = Array.from(resultDom.children).slice(9);
-        for (const child of childrenToTrim) {
-            child.remove();
+        const {data: results} = await window.$http.get('/search/suggest', {term: search});
+        if (!this.input.value) {
+            return;
         }
+        
+        const resultDom = htmlToDom(results);
 
         this.suggestionResultsWrap.innerHTML = '';
+        this.suggestionResultsWrap.style.opacity = '1';
+        this.loadingWrap.style.display = 'none';
         this.suggestionResultsWrap.append(resultDom);
         if (!this.container.classList.contains('search-active')) {
             this.showSuggestions();
@@ -45,8 +69,6 @@ class GlobalSearch {
 
     showSuggestions() {
         this.container.classList.add('search-active');
-        document.addEventListener('click', this.hideOnOuterEventListener);
-        document.addEventListener('focusin', this.hideOnOuterEventListener);
         window.requestAnimationFrame(() => {
             this.suggestions.classList.add('search-suggestions-animation');
         })
@@ -56,15 +78,5 @@ class GlobalSearch {
         this.container.classList.remove('search-active');
         this.suggestions.classList.remove('search-suggestions-animation');
         this.suggestionResultsWrap.innerHTML = '';
-        document.removeEventListener('click', this.hideOnOuterEventListener);
-        document.removeEventListener('focusin', this.hideOnOuterEventListener);
     }
-
-    hideOnOuterEventListener(event) {
-        if (!this.container.contains(event.target)) {
-            this.hideSuggestions();
-        }
-    };
-}
-
-export default GlobalSearch;
\ No newline at end of file
+}
\ No newline at end of file