diff --git a/app/assets/javascripts/shared/combobox.js b/app/assets/javascripts/shared/combobox.js index c675f8454..1adad9ddd 100644 --- a/app/assets/javascripts/shared/combobox.js +++ b/app/assets/javascripts/shared/combobox.js @@ -39,15 +39,26 @@ class ComboBox { if (this.config.includes('filter')) { const idSuffix = Math.random().toString(36); this.$comboboxMenu.append( - `
\ + `
\ \ - \ + \ No results.
` ); this.$filter = this.$comboboxMenu.find( '[data-behavior~=combobox-filter]' ); + + if (this.config.includes('add-options')) { + this.$filter.parent().append( + `\ + \ + Create ${this.$filter.val()} option\ + ` + ); + this.$filter.attr('placeholder', 'Filter or create options...'); + this.$addOption = this.$filter.siblings('[data-behavior~=add-option]'); + } } this.$target.children().each(function () { @@ -125,6 +136,13 @@ class ComboBox { }); } + if (this.$addOption) { + this.$addOption.on('click', function () { + const value = $(this).find('strong').text(); + that.appendCustomOption(value); + }); + } + this.$target.on('change', function () { let $options = []; @@ -153,12 +171,34 @@ class ComboBox { `\ - ${$option.text()}\ + data-value="${$option.attr('value')}"\ + >\ + ${$option.text()}\ ` ); } + appendCustomOption(value) { + this.$target.append(``); + + const $option = this.$target.children().last(), + that = this; + + this.appendOption(this.$comboboxMenu, $option); + + this.$comboboxOptions = this.$comboboxMenu.find( + '[data-behavior~=combobox-option]' + ); + + const $comboboxOption = this.$comboboxOptions.last(); + this.selectOptions($comboboxOption); + + $comboboxOption.on('click', function (event) { + event.stopPropagation(); + that.selectOptions($comboboxOption); + }); + } + handleFiltering() { clearTimeout(this.debounceTimeout); @@ -181,9 +221,18 @@ class ComboBox { this.$comboboxMenu.find('[data-behavior~=combobox-optgroup]'); - this.$filter - .next('[data-behavior~=no-results]') - .toggleClass('d-none', matchedOptions > 0); + if (this.config.includes('add-options')) { + this.$filter + .nextAll('[data-behavior~=add-option]') + .find('strong') + .text(this.$filter.val()) + .end() + .toggleClass('d-none', matchedOptions > 0); + } else { + this.$filter + .next('[data-behavior~=no-results]') + .toggleClass('d-none', matchedOptions > 0); + } }, this.debounceTimer); }