]> BookStack Code Mirror - bookstack/blob - resources/js/components/dropdown-search.js
Merge branch 'tinymce' into development
[bookstack] / resources / js / components / dropdown-search.js
1 import {debounce} from "../services/util";
2
3 class DropdownSearch {
4
5     setup() {
6         this.elem = this.$el;
7         this.searchInput = this.$refs.searchInput;
8         this.loadingElem = this.$refs.loading;
9         this.listContainerElem = this.$refs.listContainer;
10
11         this.localSearchSelector = this.$opts.localSearchSelector;
12         this.url = this.$opts.url;
13
14         this.elem.addEventListener('show', this.onShow.bind(this));
15         this.searchInput.addEventListener('input', this.onSearch.bind(this));
16
17         this.runAjaxSearch = debounce(this.runAjaxSearch, 300, false);
18     }
19
20     onShow() {
21         this.loadList();
22     }
23
24     onSearch() {
25         const input = this.searchInput.value.toLowerCase().trim();
26         if (this.localSearchSelector) {
27             this.runLocalSearch(input);
28         } else {
29             this.toggleLoading(true);
30             this.listContainerElem.innerHTML = '';
31             this.runAjaxSearch(input);
32         }
33     }
34
35     runAjaxSearch(searchTerm) {
36         this.loadList(searchTerm);
37     }
38
39     runLocalSearch(searchTerm) {
40         const listItems = this.listContainerElem.querySelectorAll(this.localSearchSelector);
41         for (let listItem of listItems) {
42             const match = !searchTerm || listItem.textContent.toLowerCase().includes(searchTerm);
43             listItem.style.display = match ? 'flex' : 'none';
44             listItem.classList.toggle('hidden', !match);
45         }
46     }
47
48     async loadList(searchTerm = '') {
49         this.listContainerElem.innerHTML = '';
50         this.toggleLoading(true);
51
52         try {
53             const resp = await window.$http.get(this.getAjaxUrl(searchTerm));
54             this.listContainerElem.innerHTML = resp.data;
55         } catch (err) {
56             console.error(err);
57         }
58
59         this.toggleLoading(false);
60         if (this.localSearchSelector) {
61             this.onSearch();
62         }
63     }
64
65     getAjaxUrl(searchTerm = null) {
66         if (!searchTerm) {
67             return this.url;
68         }
69
70         const joiner = this.url.includes('?') ? '&' : '?';
71         return `${this.url}${joiner}search=${encodeURIComponent(searchTerm)}`;
72     }
73
74     toggleLoading(show = false) {
75         this.loadingElem.style.display = show ? 'block' : 'none';
76     }
77
78 }
79
80 export default DropdownSearch;