import { App } from '../../gogocarto' import { anyToArray } from '../../utils/array' import { FilterAbstractComponent } from './filter-abstract.component' declare let L: any interface CustomJQuery extends JQuery { gogoAutocomplete(options: JQueryUI.AutocompleteOptions): JQuery gogoAutocomplete(methodName: 'search', value?: string): void } export class FilterValueComponent extends FilterAbstractComponent { initialize(): void { switch (this.filter.subtype) { case 'autocompletion': this.initializeAutocompletion() break case 'dropdown': App.ajaxModule.onNewElements.do((result) => { this.initializeDropdown() }) } } initializeAutocompletion(): void { const self = this $.widget('custom.gogoAutocomplete', $.ui.autocomplete, { _resizeMenu: () => { // Intentionally left empty }, _renderItem: (ul, item) => { return self.renderResults(ul, item) }, }) const $filterValueInput = $('.filter-value-input-' + self.filter.id) as CustomJQuery $filterValueInput.gogoAutocomplete({ minLength: 3, appendTo: '.filter-value-input-container-' + $filterValueInput.attr('data-filter-id'), source: function (params, response) { const searchTerm = params.term const field = self.filter.field const resultItems = [] App.elementsModule.allElements().forEach((element) => { const elementValues = anyToArray(element.data[field]) elementValues.forEach((elementValue) => { let optionInSettings = null if (self.filter?.options?.values) { optionInSettings = self.filter?.options?.values.find((option) => option.value === elementValue) } const elementLabel = optionInSettings ? optionInSettings.label : elementValue if ( elementValue && (elementLabel.toString().toLowerCase().includes(searchTerm.toLowerCase()) || elementValue.toString().toLowerCase().includes(searchTerm.toLowerCase())) && !resultItems.find((resultItem) => elementLabel == resultItem.label) ) { resultItems.push({ label: elementLabel, data: JSON.stringify({ value: elementLabel, hasResults: true, }), }) } }) }) resultItems.sort((a, b) => a.label.localeCompare(b.label)) response(resultItems) }, select: function (e, ui) { $filterValueInput.val(ui.item.value) self.filter.currentValue = { value: ui.item.value, } self.emitFilterSet() }, response: function (event, ui) { if (!ui.content.length) { const noResult = { data: '{ "hasResults": false }' } ui.content.push(noResult) } }, }) } renderResults(ul, { data }) { if (!data) { return '' // Handle case where data is not available yet } let $li = null const json = JSON.parse(data) const { value, hasResults } = json if (!hasResults) { $li = $(`
  • ${App.config.i18n[App.config.language]['no.result.found']}
  • `) } else { const meta = '' $li = $(`
  • ${value}
  • `) } return $li.appendTo(ul) } initializeDropdown(): void { const self = this const field = self.filter.field const $filterValueSelect = $('.filter-value-input-' + self.filter.id) as CustomJQuery $filterValueSelect.find('option[value]').remove() const values = App.elementsModule.allElements().map((element) => element.data[field]) const uniqueValues = ['- ' + App.config.i18n[App.config.language]['empty.value'] + ' -'] values.forEach((value) => { anyToArray(value).forEach((value) => { if (value && !uniqueValues.includes(value)) { uniqueValues.push(value) } }) }) uniqueValues.sort().forEach((optionValue, index) => { const option = document.createElement('option') option.value = optionValue let optionInSettings = null if (self.filter?.options?.values) { optionInSettings = self.filter?.options?.values.find((option) => option.value === optionValue) } option.textContent = optionInSettings ? optionInSettings.label : option.value if (index == 0) { option.value = '' } $filterValueSelect.append(option) }) $filterValueSelect.show() $filterValueSelect.on('change', function () { const selectElement = this as HTMLSelectElement if (selectElement.selectedIndex === 0) { self.clearButton.click() } else { self.filter.currentValue = { value: $(this).val(), } self.emitFilterSet() } }) } }