BookStack/resources/js/components/dropdown-search.js
Dan Brown f41c02cbd7
Some checks are pending
lint-js / build (push) Waiting to run
test-js / build (push) Waiting to run
TS: Converted app file and animations service
Extracted functions out of app file during changes to clean up.
Altered animation function to use normal css prop names instead of JS
CSS prop names.
2024-10-11 15:19:19 +01:00

83 lines
2.4 KiB
JavaScript

import {debounce} from '../services/util.ts';
import {transitionHeight} from '../services/animations.ts';
import {Component} from './component';
export class DropdownSearch extends Component {
setup() {
this.elem = this.$el;
this.searchInput = this.$refs.searchInput;
this.loadingElem = this.$refs.loading;
this.listContainerElem = this.$refs.listContainer;
this.localSearchSelector = this.$opts.localSearchSelector;
this.url = this.$opts.url;
this.elem.addEventListener('show', this.onShow.bind(this));
this.searchInput.addEventListener('input', this.onSearch.bind(this));
this.runAjaxSearch = debounce(this.runAjaxSearch, 300, false);
}
onShow() {
this.loadList();
}
onSearch() {
const input = this.searchInput.value.toLowerCase().trim();
if (this.localSearchSelector) {
this.runLocalSearch(input);
} else {
this.toggleLoading(true);
this.listContainerElem.innerHTML = '';
this.runAjaxSearch(input);
}
}
runAjaxSearch(searchTerm) {
this.loadList(searchTerm);
}
runLocalSearch(searchTerm) {
const listItems = this.listContainerElem.querySelectorAll(this.localSearchSelector);
for (const listItem of listItems) {
const match = !searchTerm || listItem.textContent.toLowerCase().includes(searchTerm);
listItem.style.display = match ? 'flex' : 'none';
listItem.classList.toggle('hidden', !match);
}
}
async loadList(searchTerm = '') {
this.listContainerElem.innerHTML = '';
this.toggleLoading(true);
try {
const resp = await window.$http.get(this.getAjaxUrl(searchTerm));
const animate = transitionHeight(this.listContainerElem, 80);
this.listContainerElem.innerHTML = resp.data;
animate();
} catch (err) {
console.error(err);
}
this.toggleLoading(false);
if (this.localSearchSelector) {
this.onSearch();
}
}
getAjaxUrl(searchTerm = null) {
if (!searchTerm) {
return this.url;
}
const joiner = this.url.includes('?') ? '&' : '?';
return `${this.url}${joiner}search=${encodeURIComponent(searchTerm)}`;
}
toggleLoading(show = false) {
this.loadingElem.style.display = show ? 'block' : 'none';
}
}