98 lines
2.4 KiB
JavaScript
98 lines
2.4 KiB
JavaScript
import _ from 'underscore';
|
|
|
|
/**
|
|
* Makes search request for content when user types a value in the search input.
|
|
* Updates the html content of the page with the received one.
|
|
*/
|
|
|
|
export default class FilterableList {
|
|
constructor(form, filter, holder, filterInputField = 'filter_groups') {
|
|
this.filterForm = form;
|
|
this.listFilterElement = filter;
|
|
this.listHolderElement = holder;
|
|
this.filterInputField = filterInputField;
|
|
this.isBusy = false;
|
|
}
|
|
|
|
getFilterEndpoint() {
|
|
return `${this.filterForm.getAttribute('action')}?${$(this.filterForm).serialize()}`;
|
|
}
|
|
|
|
getPagePath() {
|
|
return this.getFilterEndpoint();
|
|
}
|
|
|
|
initSearch() {
|
|
// Wrap to prevent passing event arguments to .filterResults;
|
|
this.debounceFilter = _.debounce(this.onFilterInput.bind(this), 500);
|
|
|
|
this.unbindEvents();
|
|
this.bindEvents();
|
|
}
|
|
|
|
onFilterInput() {
|
|
const $form = $(this.filterForm);
|
|
const queryData = {};
|
|
const filterGroupsParam = $form.find(`[name="${this.filterInputField}"]`).val();
|
|
|
|
if (filterGroupsParam) {
|
|
queryData[this.filterInputField] = filterGroupsParam;
|
|
}
|
|
|
|
this.filterResults(queryData);
|
|
|
|
if (this.setDefaultFilterOption) {
|
|
this.setDefaultFilterOption();
|
|
}
|
|
}
|
|
|
|
bindEvents() {
|
|
this.listFilterElement.addEventListener('input', this.debounceFilter);
|
|
}
|
|
|
|
unbindEvents() {
|
|
this.listFilterElement.removeEventListener('input', this.debounceFilter);
|
|
}
|
|
|
|
filterResults(queryData) {
|
|
if (this.isBusy) {
|
|
return false;
|
|
}
|
|
|
|
$(this.listHolderElement).fadeTo(250, 0.5);
|
|
|
|
return $.ajax({
|
|
url: this.getFilterEndpoint(),
|
|
data: queryData,
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
context: this,
|
|
complete: this.onFilterComplete,
|
|
beforeSend: () => {
|
|
this.isBusy = true;
|
|
},
|
|
success: (response, textStatus, xhr) => {
|
|
this.onFilterSuccess(response, xhr, queryData);
|
|
},
|
|
});
|
|
}
|
|
|
|
onFilterSuccess(response, xhr, queryData) {
|
|
if (response.html) {
|
|
this.listHolderElement.innerHTML = response.html;
|
|
}
|
|
|
|
// Change url so if user reload a page - search results are saved
|
|
const currentPath = this.getPagePath(queryData);
|
|
|
|
return window.history.replaceState({
|
|
page: currentPath,
|
|
}, document.title, currentPath);
|
|
}
|
|
|
|
onFilterComplete() {
|
|
this.isBusy = false;
|
|
$(this.listHolderElement).fadeTo(250, 1);
|
|
}
|
|
}
|