2022-03-03 18:19:46 +00:00
|
|
|
import { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js';
|
2021-02-14 18:09:20 +00:00
|
|
|
import { FILTER_TYPE } from './constants';
|
2018-02-21 20:22:56 +00:00
|
|
|
import DropdownUtils from './dropdown_utils';
|
|
|
|
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
|
2020-01-02 13:03:23 +00:00
|
|
|
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
|
2018-02-21 20:22:56 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
|
|
|
|
|
2018-02-21 20:22:56 +00:00
|
|
|
export default class FilteredSearchDropdown {
|
2017-07-20 19:17:34 +00:00
|
|
|
constructor({ droplab, dropdown, input, filter }) {
|
2017-04-17 07:01:11 +00:00
|
|
|
this.droplab = droplab;
|
|
|
|
this.hookId = input && input.id;
|
|
|
|
this.input = input;
|
|
|
|
this.filter = filter;
|
|
|
|
this.dropdown = dropdown;
|
|
|
|
this.loadingTemplate = `<div class="filter-dropdown-loading">
|
2022-03-03 18:19:46 +00:00
|
|
|
${loadingIconForLegacyJS().outerHTML}
|
2017-04-17 07:01:11 +00:00
|
|
|
</div>`;
|
|
|
|
this.bindEvents();
|
|
|
|
}
|
2016-12-02 21:04:10 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
bindEvents() {
|
|
|
|
this.itemClickedWrapper = this.itemClicked.bind(this);
|
|
|
|
this.dropdown.addEventListener('click.dl', this.itemClickedWrapper);
|
|
|
|
}
|
2016-12-09 17:44:09 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
unbindEvents() {
|
|
|
|
this.dropdown.removeEventListener('click.dl', this.itemClickedWrapper);
|
|
|
|
}
|
2016-12-02 21:04:10 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
getCurrentHook() {
|
2020-12-23 21:10:24 +00:00
|
|
|
return this.droplab.hooks.filter((h) => h.id === this.hookId)[0] || null;
|
2017-04-17 07:01:11 +00:00
|
|
|
}
|
2016-12-12 15:55:27 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
itemClicked(e, getValueFunction) {
|
|
|
|
const { selected } = e.detail;
|
|
|
|
if (selected.tagName === 'LI' && selected.innerHTML) {
|
2020-01-02 13:03:23 +00:00
|
|
|
const {
|
|
|
|
lastVisualToken: visualToken,
|
|
|
|
} = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
|
|
|
|
const { tokenOperator } = DropdownUtils.getVisualTokenValues(visualToken);
|
|
|
|
|
|
|
|
const dataValueSet = DropdownUtils.setDataValueIfSelected(
|
|
|
|
this.filter,
|
|
|
|
tokenOperator,
|
|
|
|
selected,
|
|
|
|
);
|
2016-12-12 15:55:27 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
if (!dataValueSet) {
|
|
|
|
const value = getValueFunction(selected);
|
2020-01-02 13:03:23 +00:00
|
|
|
FilteredSearchDropdownManager.addWordToInput({
|
|
|
|
tokenName: this.filter,
|
|
|
|
tokenOperator,
|
|
|
|
tokenValue: value,
|
|
|
|
clicked: true,
|
|
|
|
});
|
2016-12-16 05:20:31 +00:00
|
|
|
}
|
2016-12-02 21:04:10 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
this.resetFilters();
|
|
|
|
this.dismissDropdown();
|
|
|
|
this.dispatchInputEvent();
|
2016-12-02 21:04:10 +00:00
|
|
|
}
|
2017-04-17 07:01:11 +00:00
|
|
|
}
|
2016-12-02 21:04:10 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
setAsDropdown() {
|
|
|
|
this.input.setAttribute(DATA_DROPDOWN_TRIGGER, `#${this.dropdown.id}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
setOffset(offset = 0) {
|
|
|
|
if (window.innerWidth > 480) {
|
|
|
|
this.dropdown.style.left = `${offset}px`;
|
|
|
|
} else {
|
|
|
|
this.dropdown.style.left = '0px';
|
2016-12-05 21:12:34 +00:00
|
|
|
}
|
2017-04-17 07:01:11 +00:00
|
|
|
}
|
2016-12-05 21:12:34 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
renderContent(forceShowList = false) {
|
|
|
|
const currentHook = this.getCurrentHook();
|
2020-05-07 03:09:46 +00:00
|
|
|
|
|
|
|
FilteredSearchDropdown.hideDropdownItemsforNotOperator(currentHook);
|
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
if (forceShowList && currentHook && currentHook.list.hidden) {
|
|
|
|
currentHook.list.show();
|
2016-12-09 19:15:09 +00:00
|
|
|
}
|
2017-04-17 07:01:11 +00:00
|
|
|
}
|
2016-12-02 21:04:10 +00:00
|
|
|
|
2020-10-21 15:10:28 +00:00
|
|
|
render(forceRenderContent = false, forceShowList = false, hideNotEqual = false) {
|
2017-04-17 07:01:11 +00:00
|
|
|
this.setAsDropdown();
|
2016-12-02 21:04:10 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
const currentHook = this.getCurrentHook();
|
|
|
|
const firstTimeInitialized = currentHook === null;
|
2016-12-07 18:55:03 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
if (firstTimeInitialized || forceRenderContent) {
|
2020-10-21 15:10:28 +00:00
|
|
|
this.renderContent(forceShowList, hideNotEqual);
|
2017-04-17 07:01:11 +00:00
|
|
|
} else if (currentHook.list.list.id !== this.dropdown.id) {
|
2020-10-21 15:10:28 +00:00
|
|
|
this.renderContent(forceShowList, hideNotEqual);
|
2016-12-02 21:04:10 +00:00
|
|
|
}
|
2017-04-17 07:01:11 +00:00
|
|
|
}
|
2016-12-08 21:36:54 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
dismissDropdown() {
|
|
|
|
// Focusing on the input will dismiss dropdown
|
|
|
|
// (default droplab functionality)
|
|
|
|
this.input.focus();
|
|
|
|
}
|
2016-12-12 16:28:22 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
dispatchInputEvent() {
|
2018-10-30 10:53:01 +00:00
|
|
|
// Propagate input change to FilteredSearchDropdownManager
|
2017-04-17 07:01:11 +00:00
|
|
|
// so that it can determine which dropdowns to open
|
2018-10-10 06:18:49 +00:00
|
|
|
this.input.dispatchEvent(
|
|
|
|
new CustomEvent('input', {
|
|
|
|
bubbles: true,
|
|
|
|
cancelable: true,
|
|
|
|
}),
|
|
|
|
);
|
2017-04-17 07:01:11 +00:00
|
|
|
}
|
2016-12-12 16:28:22 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
dispatchFormSubmitEvent() {
|
|
|
|
// dispatchEvent() is necessary as form.submit() does not
|
|
|
|
// trigger event handlers
|
|
|
|
this.input.form.dispatchEvent(new Event('submit'));
|
|
|
|
}
|
2017-01-21 07:44:36 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
hideDropdown() {
|
|
|
|
const currentHook = this.getCurrentHook();
|
|
|
|
if (currentHook) {
|
|
|
|
currentHook.list.hide();
|
2016-12-09 21:47:56 +00:00
|
|
|
}
|
2017-04-17 07:01:11 +00:00
|
|
|
}
|
2016-12-09 22:02:43 +00:00
|
|
|
|
2017-04-17 07:01:11 +00:00
|
|
|
resetFilters() {
|
|
|
|
const hook = this.getCurrentHook();
|
|
|
|
|
|
|
|
if (hook) {
|
|
|
|
const data = hook.list.data || [];
|
2018-02-21 15:17:03 +00:00
|
|
|
|
|
|
|
if (!data) return;
|
|
|
|
|
2020-12-23 21:10:24 +00:00
|
|
|
const results = data.map((o) => {
|
2017-04-17 07:01:11 +00:00
|
|
|
const updated = o;
|
|
|
|
updated.droplab_hidden = false;
|
|
|
|
return updated;
|
|
|
|
});
|
|
|
|
hook.list.render(results);
|
2016-12-09 22:02:43 +00:00
|
|
|
}
|
2016-12-02 21:04:10 +00:00
|
|
|
}
|
2020-05-07 03:09:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Hide None & Any options from the current dropdown.
|
|
|
|
* Hiding happens only for NOT operator.
|
|
|
|
*/
|
|
|
|
static hideDropdownItemsforNotOperator(currentHook) {
|
|
|
|
const lastOperator = FilteredSearchVisualTokens.getLastTokenOperator();
|
|
|
|
|
|
|
|
if (lastOperator === '!=') {
|
|
|
|
const { list: dropdownEl } = currentHook.list;
|
|
|
|
|
|
|
|
let shouldHideDivider = true;
|
|
|
|
|
|
|
|
// Iterate over all the static dropdown values,
|
|
|
|
// then hide `None` and `Any` items.
|
2020-12-23 21:10:24 +00:00
|
|
|
Array.from(dropdownEl.querySelectorAll('li[data-value]')).forEach((itemEl) => {
|
2020-05-07 03:09:46 +00:00
|
|
|
const {
|
|
|
|
dataset: { value },
|
|
|
|
} = itemEl;
|
|
|
|
|
|
|
|
if (value.toLowerCase() === FILTER_TYPE.none || value.toLowerCase() === FILTER_TYPE.any) {
|
|
|
|
itemEl.classList.add('hidden');
|
|
|
|
} else {
|
|
|
|
// If we encountered any element other than None/Any, then
|
|
|
|
// we shouldn't hide the divider
|
|
|
|
shouldHideDivider = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (shouldHideDivider) {
|
|
|
|
const divider = dropdownEl.querySelector('li.divider');
|
|
|
|
if (divider) {
|
|
|
|
divider.classList.add('hidden');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-17 07:01:11 +00:00
|
|
|
}
|