]> BookStack Code Mirror - bookstack/blob - resources/js/components/global-search.js
Fixed input styles in search preview mode, added animation
[bookstack] / resources / js / components / global-search.js
1 /**
2  * @extends {Component}
3  */
4 import {htmlToDom} from "../services/dom";
5
6 class GlobalSearch {
7
8     setup() {
9         this.container = this.$el;
10         this.input = this.$refs.input;
11         this.suggestions = this.$refs.suggestions;
12         this.suggestionResultsWrap = this.$refs.suggestionResults;
13
14         this.setupListeners();
15     }
16
17     setupListeners() {
18         this.hideOnOuterEventListener = this.hideOnOuterEventListener.bind(this);
19
20         this.input.addEventListener('input', () => {
21             const value = this.input.value;
22             if (value.length > 0) {
23                 this.updateSuggestions(value);
24             }  else {
25                 this.hideSuggestions();
26             }
27         });
28     }
29
30     async updateSuggestions(search) {
31         const {data: results} = await window.$http.get('/ajax/search/entities', {term: search, count: 5});
32         const resultDom = htmlToDom(results);
33
34         const childrenToTrim = Array.from(resultDom.children).slice(9);
35         for (const child of childrenToTrim) {
36             child.remove();
37         }
38
39         this.suggestionResultsWrap.innerHTML = '';
40         this.suggestionResultsWrap.append(resultDom);
41         if (!this.container.classList.contains('search-active')) {
42             this.showSuggestions();
43         }
44     }
45
46     showSuggestions() {
47         this.container.classList.add('search-active');
48         document.addEventListener('click', this.hideOnOuterEventListener);
49         document.addEventListener('focusin', this.hideOnOuterEventListener);
50         window.requestAnimationFrame(() => {
51             this.suggestions.classList.add('search-suggestions-animation');
52         })
53     }
54
55     hideSuggestions() {
56         this.container.classList.remove('search-active');
57         this.suggestions.classList.remove('search-suggestions-animation');
58         this.suggestionResultsWrap.innerHTML = '';
59         document.removeEventListener('click', this.hideOnOuterEventListener);
60         document.removeEventListener('focusin', this.hideOnOuterEventListener);
61     }
62
63     hideOnOuterEventListener(event) {
64         if (!this.container.contains(event.target)) {
65             this.hideSuggestions();
66         }
67     };
68 }
69
70 export default GlobalSearch;