From 6424bd40082ca2c03e656311d9c8dbb4db886570 Mon Sep 17 00:00:00 2001 From: Josenilton Junior Date: Fri, 3 May 2024 17:39:49 -0300 Subject: [PATCH 1/3] [Autocomplete] Fix grouped options order --- src/Autocomplete/assets/dist/controller.js | 38 ++++++++++++-- src/Autocomplete/assets/src/controller.ts | 58 ++++++++++++++++++---- 2 files changed, 84 insertions(+), 12 deletions(-) diff --git a/src/Autocomplete/assets/dist/controller.js b/src/Autocomplete/assets/dist/controller.js index 7d9d148dd2..a3bc6bc596 100644 --- a/src/Autocomplete/assets/dist/controller.js +++ b/src/Autocomplete/assets/dist/controller.js @@ -195,11 +195,9 @@ class default_1 extends Controller { } createOptionsDataStructure(selectElement) { return Array.from(selectElement.options).map((option) => { - const optgroup = option.closest('optgroup'); return { value: option.value, text: option.text, - group: optgroup ? optgroup.label : null, }; }); } @@ -216,7 +214,7 @@ class default_1 extends Controller { if (filteredOriginalOptions.length !== filteredNewOptions.length) { return false; } - const normalizeOption = (option) => `${option.value}-${option.text}-${option.group}`; + const normalizeOption = (option) => `${option.value}-${option.text}`; const originalOptionsSet = new Set(filteredOriginalOptions.map(normalizeOption)); const newOptionsSet = new Set(filteredNewOptions.map(normalizeOption)); return (originalOptionsSet.size === newOptionsSet.size && @@ -250,6 +248,40 @@ _default_1_instances = new WeakSet(), _default_1_getCommonConfig = function _def this.tomSelect.setTextboxValue(''); }, closeAfterSelect: true, + onOptionAdd: (value, data) => { + let parentElement = this.tomSelect.input; + let optgroupData = null; + const optgroup = data[this.tomSelect.settings.optgroupField]; + if (optgroup && this.tomSelect.optgroups) { + optgroupData = this.tomSelect.optgroups[optgroup]; + if (optgroupData) { + const optgroupElement = parentElement.querySelector(`optgroup[label="${optgroupData.label}"]`); + if (optgroupElement) { + parentElement = optgroupElement; + } + } + } + const optionElement = document.createElement('option'); + optionElement.value = value; + optionElement.text = data[this.tomSelect.settings.labelField]; + const optionOrder = data['$order']; + let orderedOption = null; + for (const [, tomSelectOption] of Object.entries(this.tomSelect.options)) { + if (tomSelectOption['$order'] === optionOrder) { + orderedOption = parentElement.querySelector(`:scope > option[value="${tomSelectOption[this.tomSelect.settings.valueField]}"]`); + break; + } + } + if (orderedOption) { + orderedOption.insertAdjacentElement('afterend', optionElement); + } + else if (optionOrder >= 0) { + parentElement.append(optionElement); + } + else { + parentElement.prepend(optionElement); + } + }, }; if (!this.selectElement && !this.urlValue) { config.shouldLoad = () => false; diff --git a/src/Autocomplete/assets/src/controller.ts b/src/Autocomplete/assets/src/controller.ts index 62fe734ecb..379621cf55 100644 --- a/src/Autocomplete/assets/src/controller.ts +++ b/src/Autocomplete/assets/src/controller.ts @@ -17,6 +17,10 @@ export interface AutocompleteConnectOptions { tomSelect: TomSelect; options: any; } +interface OptionDataStructure { + value: string; + text: string; +} export default class extends Controller { static values = { @@ -47,7 +51,7 @@ export default class extends Controller { private mutationObserver: MutationObserver; private isObserving = false; private hasLoadedChoicesPreviously = false; - private originalOptions: Array<{ value: string; text: string; group: string | null }> = []; + private originalOptions: Array = []; initialize() { if (!this.mutationObserver) { @@ -158,6 +162,47 @@ export default class extends Controller { this.tomSelect.setTextboxValue(''); }, closeAfterSelect: true, + // fix positioning (in the dropdown) of options added through addOption() + onOptionAdd: (value: string, data: { [key: string]: any }) => { + let parentElement = this.tomSelect.input as Element; + let optgroupData = null; + + const optgroup = data[this.tomSelect.settings.optgroupField]; + if (optgroup && this.tomSelect.optgroups) { + optgroupData = this.tomSelect.optgroups[optgroup]; + if (optgroupData) { + const optgroupElement = parentElement.querySelector(`optgroup[label="${optgroupData.label}"]`); + if (optgroupElement) { + parentElement = optgroupElement; + } + } + } + + const optionElement = document.createElement('option'); + optionElement.value = value; + optionElement.text = data[this.tomSelect.settings.labelField]; + + const optionOrder = data['$order']; + let orderedOption = null; + + for (const [, tomSelectOption] of Object.entries(this.tomSelect.options)) { + if (tomSelectOption['$order'] === optionOrder) { + orderedOption = parentElement.querySelector( + `:scope > option[value="${tomSelectOption[this.tomSelect.settings.valueField]}"]` + ); + + break; + } + } + + if (orderedOption) { + orderedOption.insertAdjacentElement('afterend', optionElement); + } else if (optionOrder >= 0) { + parentElement.append(optionElement); + } else { + parentElement.prepend(optionElement); + } + }, }; // for non-autocompleting input elements, avoid the "No results" message that always shows @@ -414,20 +459,16 @@ export default class extends Controller { } } - private createOptionsDataStructure( - selectElement: HTMLSelectElement - ): Array<{ value: string; text: string; group: string | null }> { + private createOptionsDataStructure(selectElement: HTMLSelectElement): Array { return Array.from(selectElement.options).map((option) => { - const optgroup = option.closest('optgroup'); return { value: option.value, text: option.text, - group: optgroup ? optgroup.label : null, }; }); } - private areOptionsEquivalent(newOptions: Array<{ value: string; text: string; group: string | null }>): boolean { + private areOptionsEquivalent(newOptions: Array): boolean { // remove the empty option, which is added by TomSelect so may be missing from new options const filteredOriginalOptions = this.originalOptions.filter((option) => option.value !== ''); const filteredNewOptions = newOptions.filter((option) => option.value !== ''); @@ -447,8 +488,7 @@ export default class extends Controller { return false; } - const normalizeOption = (option: { value: string; text: string; group: string | null }) => - `${option.value}-${option.text}-${option.group}`; + const normalizeOption = (option: OptionDataStructure) => `${option.value}-${option.text}`; const originalOptionsSet = new Set(filteredOriginalOptions.map(normalizeOption)); const newOptionsSet = new Set(filteredNewOptions.map(normalizeOption)); From 07b3eeb55b3d4eeacaf188b6f1ae5847b30b33aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Andr=C3=A9?= Date: Wed, 6 Nov 2024 19:09:52 +0100 Subject: [PATCH 2/3] Build up to date packages --- src/Autocomplete/assets/dist/controller.js | 4 ++-- src/Autocomplete/assets/src/controller.ts | 4 ++-- yarn.lock | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Autocomplete/assets/dist/controller.js b/src/Autocomplete/assets/dist/controller.js index a3bc6bc596..bc70b563f9 100644 --- a/src/Autocomplete/assets/dist/controller.js +++ b/src/Autocomplete/assets/dist/controller.js @@ -264,10 +264,10 @@ _default_1_instances = new WeakSet(), _default_1_getCommonConfig = function _def const optionElement = document.createElement('option'); optionElement.value = value; optionElement.text = data[this.tomSelect.settings.labelField]; - const optionOrder = data['$order']; + const optionOrder = data.$order; let orderedOption = null; for (const [, tomSelectOption] of Object.entries(this.tomSelect.options)) { - if (tomSelectOption['$order'] === optionOrder) { + if (tomSelectOption.$order === optionOrder) { orderedOption = parentElement.querySelector(`:scope > option[value="${tomSelectOption[this.tomSelect.settings.valueField]}"]`); break; } diff --git a/src/Autocomplete/assets/src/controller.ts b/src/Autocomplete/assets/src/controller.ts index 379621cf55..5cefe2ec97 100644 --- a/src/Autocomplete/assets/src/controller.ts +++ b/src/Autocomplete/assets/src/controller.ts @@ -182,11 +182,11 @@ export default class extends Controller { optionElement.value = value; optionElement.text = data[this.tomSelect.settings.labelField]; - const optionOrder = data['$order']; + const optionOrder = data.$order; let orderedOption = null; for (const [, tomSelectOption] of Object.entries(this.tomSelect.options)) { - if (tomSelectOption['$order'] === optionOrder) { + if (tomSelectOption.$order === optionOrder) { orderedOption = parentElement.querySelector( `:scope > option[value="${tomSelectOption[this.tomSelect.settings.valueField]}"]` ); diff --git a/yarn.lock b/yarn.lock index 27e8d36923..963b1538a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2856,7 +2856,7 @@ __metadata: vitest-canvas-mock: "npm:^0.3.3" peerDependencies: "@hotwired/stimulus": ^3.0.0 - chart.js: ^3.4.1 || ^4.0 + chart.js: ^4.0 languageName: unknown linkType: soft @@ -2987,7 +2987,7 @@ __metadata: svelte: "npm:^3.0 || ^4.0" peerDependencies: "@hotwired/stimulus": ^3.0.0 - svelte: ^3.0 || ^4.0 + svelte: ^4.0 languageName: unknown linkType: soft @@ -3042,7 +3042,7 @@ __metadata: "@hotwired/turbo": "npm:^7.1.0 || ^8.0" peerDependencies: "@hotwired/stimulus": ^3.0.0 - "@hotwired/turbo": ^7.1.1 || ^8.0 + "@hotwired/turbo": ^8.0 languageName: unknown linkType: soft From 4344a3c26f30e73e79e27ac53d21547ae99f13ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Andr=C3=A9?= Date: Wed, 6 Nov 2024 19:21:22 +0100 Subject: [PATCH 3/3] Yarn cleanup --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 963b1538a5..27e8d36923 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2856,7 +2856,7 @@ __metadata: vitest-canvas-mock: "npm:^0.3.3" peerDependencies: "@hotwired/stimulus": ^3.0.0 - chart.js: ^4.0 + chart.js: ^3.4.1 || ^4.0 languageName: unknown linkType: soft @@ -2987,7 +2987,7 @@ __metadata: svelte: "npm:^3.0 || ^4.0" peerDependencies: "@hotwired/stimulus": ^3.0.0 - svelte: ^4.0 + svelte: ^3.0 || ^4.0 languageName: unknown linkType: soft @@ -3042,7 +3042,7 @@ __metadata: "@hotwired/turbo": "npm:^7.1.0 || ^8.0" peerDependencies: "@hotwired/stimulus": ^3.0.0 - "@hotwired/turbo": ^8.0 + "@hotwired/turbo": ^7.1.1 || ^8.0 languageName: unknown linkType: soft