@@ -29,6 +29,7 @@ class default_1 extends Controller {
29
29
_default_1_instances . add ( this ) ;
30
30
this . isObserving = false ;
31
31
this . hasLoadedChoicesPreviously = false ;
32
+ this . originalOptions = [ ] ;
32
33
}
33
34
initialize ( ) {
34
35
if ( this . requiresLiveIgnore ( ) ) {
@@ -49,6 +50,15 @@ class default_1 extends Controller {
49
50
}
50
51
}
51
52
connect ( ) {
53
+ if ( this . selectElement ) {
54
+ this . originalOptions = this . createOptionsDataStructure ( this . selectElement ) ;
55
+ }
56
+ this . initializeTomSelect ( ) ;
57
+ }
58
+ initializeTomSelect ( ) {
59
+ if ( this . selectElement ) {
60
+ this . selectElement . setAttribute ( 'data-skip-morph' , '' ) ;
61
+ }
52
62
if ( this . urlValue ) {
53
63
this . tomSelect = __classPrivateFieldGet ( this , _default_1_instances , "m" , _default_1_createAutocompleteWithRemoteData ) . call ( this , this . urlValue , this . hasMinCharactersValue ? this . minCharactersValue : null ) ;
54
64
return ;
@@ -97,9 +107,12 @@ class default_1 extends Controller {
97
107
resetTomSelect ( ) {
98
108
if ( this . tomSelect ) {
99
109
this . stopMutationObserver ( ) ;
100
- this . tomSelect . clearOptions ( ) ;
101
- this . tomSelect . settings . maxOptions = this . getMaxOptions ( ) ;
102
- this . tomSelect . sync ( ) ;
110
+ const currentHtml = this . element . innerHTML ;
111
+ const currentValue = this . tomSelect . getValue ( ) ;
112
+ this . tomSelect . destroy ( ) ;
113
+ this . element . innerHTML = currentHtml ;
114
+ this . initializeTomSelect ( ) ;
115
+ this . tomSelect . setValue ( currentValue ) ;
103
116
this . startMutationObserver ( ) ;
104
117
}
105
118
}
@@ -113,22 +126,6 @@ class default_1 extends Controller {
113
126
}
114
127
this . startMutationObserver ( ) ;
115
128
}
116
- updateTomSelectPlaceholder ( ) {
117
- const input = this . element ;
118
- let placeholder = input . getAttribute ( 'placeholder' ) || input . getAttribute ( 'data-placeholder' ) ;
119
- if ( ! placeholder && ! this . tomSelect . allowEmptyOption ) {
120
- const option = input . querySelector ( 'option[value=""]' ) ;
121
- if ( option ) {
122
- placeholder = option . textContent ;
123
- }
124
- }
125
- if ( placeholder ) {
126
- this . stopMutationObserver ( ) ;
127
- this . tomSelect . settings . placeholder = placeholder ;
128
- this . tomSelect . control_input . setAttribute ( 'placeholder' , placeholder ) ;
129
- this . startMutationObserver ( ) ;
130
- }
131
- }
132
129
startMutationObserver ( ) {
133
130
if ( ! this . isObserving && this . mutationObserver ) {
134
131
this . mutationObserver . observe ( this . element , {
@@ -147,74 +144,51 @@ class default_1 extends Controller {
147
144
}
148
145
}
149
146
onMutations ( mutations ) {
150
- const addedOptionElements = [ ] ;
151
- const removedOptionElements = [ ] ;
152
- let hasAnOptionChanged = false ;
153
147
let changeDisabledState = false ;
154
- let changePlaceholder = false ;
155
148
mutations . forEach ( ( mutation ) => {
156
149
switch ( mutation . type ) {
157
- case 'childList' :
158
- if ( mutation . target instanceof HTMLOptionElement ) {
159
- if ( mutation . target . value === '' ) {
160
- changePlaceholder = true ;
161
- break ;
162
- }
163
- hasAnOptionChanged = true ;
164
- break ;
165
- }
166
- mutation . addedNodes . forEach ( ( node ) => {
167
- if ( node instanceof HTMLOptionElement ) {
168
- if ( removedOptionElements . includes ( node ) ) {
169
- removedOptionElements . splice ( removedOptionElements . indexOf ( node ) , 1 ) ;
170
- return ;
171
- }
172
- addedOptionElements . push ( node ) ;
173
- }
174
- } ) ;
175
- mutation . removedNodes . forEach ( ( node ) => {
176
- if ( node instanceof HTMLOptionElement ) {
177
- if ( addedOptionElements . includes ( node ) ) {
178
- addedOptionElements . splice ( addedOptionElements . indexOf ( node ) , 1 ) ;
179
- return ;
180
- }
181
- removedOptionElements . push ( node ) ;
182
- }
183
- } ) ;
184
- break ;
185
150
case 'attributes' :
186
- if ( mutation . target instanceof HTMLOptionElement ) {
187
- hasAnOptionChanged = true ;
188
- break ;
189
- }
190
151
if ( mutation . target === this . element && mutation . attributeName === 'disabled' ) {
191
152
changeDisabledState = true ;
192
153
break ;
193
154
}
194
155
break ;
195
- case 'characterData' :
196
- if ( mutation . target instanceof Text && mutation . target . parentElement instanceof HTMLOptionElement ) {
197
- if ( mutation . target . parentElement . value === '' ) {
198
- changePlaceholder = true ;
199
- break ;
200
- }
201
- hasAnOptionChanged = true ;
202
- }
203
156
}
204
157
} ) ;
205
- if ( hasAnOptionChanged || addedOptionElements . length > 0 || removedOptionElements . length > 0 ) {
158
+ const newOptions = this . selectElement ? this . createOptionsDataStructure ( this . selectElement ) : [ ] ;
159
+ const areOptionsEquivalent = this . areOptionsEquivalent ( newOptions ) ;
160
+ console . log ( 'are options equivalent?' , areOptionsEquivalent ) ;
161
+ if ( ! areOptionsEquivalent ) {
162
+ this . originalOptions = newOptions ;
206
163
this . resetTomSelect ( ) ;
207
164
}
208
165
if ( changeDisabledState ) {
209
166
this . changeTomSelectDisabledState ( this . formElement . disabled ) ;
210
167
}
211
- if ( changePlaceholder ) {
212
- this . updateTomSelectPlaceholder ( ) ;
213
- }
214
168
}
215
169
requiresLiveIgnore ( ) {
216
170
return this . element instanceof HTMLSelectElement && this . element . multiple ;
217
171
}
172
+ createOptionsDataStructure ( selectElement ) {
173
+ return Array . from ( selectElement . options ) . map ( ( option ) => {
174
+ const optgroup = option . closest ( 'optgroup' ) ;
175
+ return {
176
+ value : option . value ,
177
+ text : option . text ,
178
+ group : optgroup ? optgroup . label : null ,
179
+ } ;
180
+ } ) ;
181
+ }
182
+ areOptionsEquivalent ( newOptions ) {
183
+ if ( this . originalOptions . length !== newOptions . length ) {
184
+ return false ;
185
+ }
186
+ const normalizeOption = ( option ) => `${ option . value } -${ option . text } -${ option . group } ` ;
187
+ const originalOptionsSet = new Set ( this . originalOptions . map ( normalizeOption ) ) ;
188
+ const newOptionsSet = new Set ( newOptions . map ( normalizeOption ) ) ;
189
+ return ( originalOptionsSet . size === newOptionsSet . size &&
190
+ [ ...originalOptionsSet ] . every ( ( option ) => newOptionsSet . has ( option ) ) ) ;
191
+ }
218
192
}
219
193
_default_1_instances = new WeakSet ( ) , _default_1_getCommonConfig = function _default_1_getCommonConfig ( ) {
220
194
const plugins = { } ;
0 commit comments