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