]> BookStack Code Mirror - bookstack/blob - resources/assets/js/components/entity-selector.js
Merge pull request #1072 from CliffyPrime/german_update
[bookstack] / resources / assets / js / components / entity-selector.js
1
2 class EntitySelector {
3
4     constructor(elem) {
5         this.elem = elem;
6         this.search = '';
7         this.lastClick = 0;
8
9         let entityTypes = elem.hasAttribute('entity-types') ? elem.getAttribute('entity-types') : 'page,book,chapter';
10         let entityPermission = elem.hasAttribute('entity-permission') ? elem.getAttribute('entity-permission') : 'view';
11         this.searchUrl = window.baseUrl(`/ajax/search/entities?types=${encodeURIComponent(entityTypes)}&permission=${encodeURIComponent(entityPermission)}`);
12
13         this.input = elem.querySelector('[entity-selector-input]');
14         this.searchInput = elem.querySelector('[entity-selector-search]');
15         this.loading = elem.querySelector('[entity-selector-loading]');
16         this.resultsContainer = elem.querySelector('[entity-selector-results]');
17
18         this.elem.addEventListener('click', this.onClick.bind(this));
19
20         let lastSearch = 0;
21         this.searchInput.addEventListener('input', event => {
22             lastSearch = Date.now();
23             this.showLoading();
24             setTimeout(() => {
25                 if (Date.now() - lastSearch < 199) return;
26                 this.searchEntities(this.searchInput.value);
27             }, 200);
28         });
29         this.searchInput.addEventListener('keydown', event => {
30             if (event.keyCode === 13) event.preventDefault();
31         });
32
33         this.showLoading();
34         this.initialLoad();
35     }
36
37     showLoading() {
38         this.loading.style.display = 'block';
39         this.resultsContainer.style.display = 'none';
40     }
41
42     hideLoading() {
43         this.loading.style.display = 'none';
44         this.resultsContainer.style.display = 'block';
45     }
46
47     initialLoad() {
48         window.$http.get(this.searchUrl).then(resp => {
49             this.resultsContainer.innerHTML = resp.data;
50             this.hideLoading();
51         })
52     }
53
54     searchEntities(searchTerm) {
55         this.input.value = '';
56         let url = this.searchUrl + `&term=${encodeURIComponent(searchTerm)}`;
57         window.$http.get(url).then(resp => {
58             this.resultsContainer.innerHTML = resp.data;
59             this.hideLoading();
60         });
61     }
62
63     isDoubleClick() {
64         let now = Date.now();
65         let answer = now - this.lastClick < 300;
66         this.lastClick = now;
67         return answer;
68     }
69
70     onClick(event) {
71         let t = event.target;
72
73         if (t.matches('.entity-list-item  *')) {
74             event.preventDefault();
75             event.stopPropagation();
76             let item = t.closest('[data-entity-type]');
77             this.selectItem(item);
78         } else if (t.matches('[data-entity-type]')) {
79             this.selectItem(t)
80         }
81
82     }
83
84     selectItem(item) {
85         let isDblClick = this.isDoubleClick();
86         let type = item.getAttribute('data-entity-type');
87         let id = item.getAttribute('data-entity-id');
88         let isSelected = !item.classList.contains('selected') || isDblClick;
89
90         this.unselectAll();
91         this.input.value = isSelected ? `${type}:${id}` : '';
92
93         if (!isSelected) window.$events.emit('entity-select-change', null);
94         if (isSelected) {
95             item.classList.add('selected');
96             item.classList.add('primary-background');
97         }
98         if (!isDblClick && !isSelected) return;
99
100         let link = item.querySelector('.entity-list-item-link').getAttribute('href');
101         let name = item.querySelector('.entity-list-item-name').textContent;
102         let data = {id: Number(id), name: name, link: link};
103
104         if (isDblClick) window.$events.emit('entity-select-confirm', data);
105         if (isSelected) window.$events.emit('entity-select-change', data);
106     }
107
108     unselectAll() {
109         let selected = this.elem.querySelectorAll('.selected');
110         for (let i = 0, len = selected.length; i < len; i++) {
111             selected[i].classList.remove('selected');
112             selected[i].classList.remove('primary-background');
113         }
114     }
115
116 }
117
118 export default EntitySelector;