hotwire_combobox 0.1.41 → 0.1.43
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -0
- data/app/assets/javascripts/controllers/hw_combobox_controller.js +1 -1
- data/app/assets/javascripts/hotwire_combobox.esm.js +161 -85
- data/app/assets/javascripts/hotwire_combobox.umd.js +161 -85
- data/app/assets/javascripts/hw_combobox/models/combobox/async_loading.js +4 -0
- data/app/assets/javascripts/hw_combobox/models/combobox/autocomplete.js +8 -6
- data/app/assets/javascripts/hw_combobox/models/combobox/events.js +17 -7
- data/app/assets/javascripts/hw_combobox/models/combobox/filtering.js +19 -22
- data/app/assets/javascripts/hw_combobox/models/combobox/options.js +12 -4
- data/app/assets/javascripts/hw_combobox/models/combobox/selection.js +95 -44
- data/app/assets/javascripts/hw_combobox/models/combobox/toggle.js +13 -0
- data/app/assets/javascripts/hw_combobox/models/combobox/validity.js +1 -1
- data/app/presenters/hotwire_combobox/component.rb +2 -2
- data/lib/hotwire_combobox/engine.rb +2 -2
- data/lib/hotwire_combobox/helper.rb +26 -16
- data/lib/hotwire_combobox/version.rb +1 -1
- metadata +2 -2
@@ -41,6 +41,10 @@
|
|
41
41
|
get _isAsync() {
|
42
42
|
return this.hasAsyncSrcValue
|
43
43
|
}
|
44
|
+
|
45
|
+
get _isSync() {
|
46
|
+
return !this._isAsync
|
47
|
+
}
|
44
48
|
};
|
45
49
|
|
46
50
|
function Concerns(Base, ...mixins) {
|
@@ -132,16 +136,18 @@
|
|
132
136
|
}
|
133
137
|
}
|
134
138
|
|
135
|
-
|
136
|
-
|
139
|
+
_replaceFullQueryWithAutocompletedValue(option) {
|
140
|
+
const autocompletedValue = option.getAttribute(this.autocompletableAttributeValue);
|
141
|
+
|
142
|
+
this._fullQuery = autocompletedValue;
|
143
|
+
this._actingCombobox.setSelectionRange(autocompletedValue.length, autocompletedValue.length);
|
144
|
+
}
|
137
145
|
|
146
|
+
_autocompleteMissingPortion(option) {
|
138
147
|
const typedValue = this._typedQuery;
|
139
148
|
const autocompletedValue = option.getAttribute(this.autocompletableAttributeValue);
|
140
149
|
|
141
|
-
if (
|
142
|
-
this._fullQuery = autocompletedValue;
|
143
|
-
this._actingCombobox.setSelectionRange(autocompletedValue.length, autocompletedValue.length);
|
144
|
-
} else if (startsWith(autocompletedValue, typedValue)) {
|
150
|
+
if (this._autocompletesInline && startsWith(autocompletedValue, typedValue)) {
|
145
151
|
this._fullQuery = autocompletedValue;
|
146
152
|
this._actingCombobox.setSelectionRange(typedValue.length, autocompletedValue.length);
|
147
153
|
}
|
@@ -240,17 +246,27 @@
|
|
240
246
|
};
|
241
247
|
|
242
248
|
Combobox.Events = Base => class extends Base {
|
243
|
-
_dispatchSelectionEvent({
|
244
|
-
|
245
|
-
|
249
|
+
_dispatchSelectionEvent({ isNewAndAllowed, previousValue }) {
|
250
|
+
if (previousValue !== this._value) {
|
251
|
+
dispatch("hw-combobox:selection", {
|
252
|
+
target: this.element,
|
253
|
+
detail: { ...this._eventableDetails, isNewAndAllowed, previousValue }
|
254
|
+
});
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
_dispatchClosedEvent() {
|
259
|
+
dispatch("hw-combobox:closed", { target: this.element, detail: this._eventableDetails });
|
260
|
+
}
|
261
|
+
|
262
|
+
get _eventableDetails() {
|
263
|
+
return {
|
264
|
+
value: this._value,
|
246
265
|
display: this._fullQuery,
|
247
266
|
query: this._typedQuery,
|
248
267
|
fieldName: this.hiddenFieldTarget.name,
|
249
|
-
isValid: this._valueIsValid
|
250
|
-
|
251
|
-
};
|
252
|
-
|
253
|
-
dispatch("hw-combobox:selection", { target: this.element, detail });
|
268
|
+
isValid: this._valueIsValid
|
269
|
+
}
|
254
270
|
}
|
255
271
|
};
|
256
272
|
|
@@ -532,20 +548,28 @@
|
|
532
548
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
533
549
|
|
534
550
|
Combobox.Filtering = Base => class extends Base {
|
535
|
-
|
551
|
+
filterAndSelect(event) {
|
552
|
+
this._filter(event);
|
553
|
+
|
554
|
+
if (this._isSync) {
|
555
|
+
this._selectBasedOnQuery(event);
|
556
|
+
}
|
557
|
+
}
|
558
|
+
|
559
|
+
_initializeFiltering() {
|
560
|
+
this._debouncedFilterAsync = debounce(this._debouncedFilterAsync.bind(this));
|
561
|
+
}
|
562
|
+
|
563
|
+
_filter(event) {
|
536
564
|
if (this._isAsync) {
|
537
565
|
this._debouncedFilterAsync(event);
|
538
566
|
} else {
|
539
|
-
this._filterSync(
|
567
|
+
this._filterSync();
|
540
568
|
}
|
541
569
|
|
542
570
|
this._actingCombobox.toggleAttribute("data-queried", this._isQueried);
|
543
571
|
}
|
544
572
|
|
545
|
-
_initializeFiltering() {
|
546
|
-
this._debouncedFilterAsync = debounce(this._debouncedFilterAsync.bind(this));
|
547
|
-
}
|
548
|
-
|
549
573
|
_debouncedFilterAsync(event) {
|
550
574
|
this._filterAsync(event);
|
551
575
|
}
|
@@ -560,27 +584,14 @@
|
|
560
584
|
await get(this.asyncSrcValue, { responseKind: "turbo-stream", query });
|
561
585
|
}
|
562
586
|
|
563
|
-
_filterSync(
|
587
|
+
_filterSync() {
|
564
588
|
this.open();
|
565
589
|
this._allOptionElements.forEach(applyFilter(this._fullQuery, { matching: this.filterableAttributeValue }));
|
566
|
-
this._commitFilter(event);
|
567
|
-
}
|
568
|
-
|
569
|
-
_commitFilter(event) {
|
570
|
-
if (this._shouldTreatAsNewOptionForFiltering(!isDeleteEvent(event))) {
|
571
|
-
this._selectNew();
|
572
|
-
} else if (isDeleteEvent(event)) {
|
573
|
-
this._deselect();
|
574
|
-
} else if (event.inputType === "hw:lockInSelection") {
|
575
|
-
this._select(this._ensurableOption);
|
576
|
-
} else if (this._isOpen) {
|
577
|
-
this._select(this._visibleOptionElements[0]);
|
578
|
-
}
|
579
590
|
}
|
580
591
|
|
581
592
|
_clearQuery() {
|
582
593
|
this._fullQuery = "";
|
583
|
-
this.
|
594
|
+
this.filterAndSelect({ inputType: "deleteContentBackward" });
|
584
595
|
}
|
585
596
|
|
586
597
|
get _isQueried() {
|
@@ -674,9 +685,17 @@
|
|
674
685
|
};
|
675
686
|
|
676
687
|
Combobox.Options = Base => class extends Base {
|
677
|
-
|
678
|
-
this._deselect();
|
679
|
-
|
688
|
+
_resetOptionsSilently() {
|
689
|
+
this._resetOptions(this._deselect.bind(this));
|
690
|
+
}
|
691
|
+
|
692
|
+
_resetOptionsAndNotify() {
|
693
|
+
this._resetOptions(this._deselectAndNotify.bind(this));
|
694
|
+
}
|
695
|
+
|
696
|
+
_resetOptions(deselectionStrategy) {
|
697
|
+
this._setName(this.originalNameValue);
|
698
|
+
deselectionStrategy();
|
680
699
|
}
|
681
700
|
|
682
701
|
get _allowNew() {
|
@@ -704,7 +723,7 @@
|
|
704
723
|
}
|
705
724
|
|
706
725
|
get _isUnjustifiablyBlank() {
|
707
|
-
const valueIsMissing = !this.
|
726
|
+
const valueIsMissing = !this._value;
|
708
727
|
const noBlankOptionSelected = !this._selectedOptionElement;
|
709
728
|
|
710
729
|
return valueIsMissing && noBlankOptionSelected
|
@@ -713,8 +732,7 @@
|
|
713
732
|
|
714
733
|
Combobox.Selection = Base => class extends Base {
|
715
734
|
selectOptionOnClick(event) {
|
716
|
-
this.
|
717
|
-
this._select(event.currentTarget, { forceAutocomplete: true });
|
735
|
+
this._forceSelectionAndFilter(event.currentTarget, event);
|
718
736
|
this.close();
|
719
737
|
}
|
720
738
|
|
@@ -724,91 +742,136 @@
|
|
724
742
|
}
|
725
743
|
}
|
726
744
|
|
727
|
-
|
728
|
-
this.
|
729
|
-
|
730
|
-
if (
|
731
|
-
this.
|
732
|
-
|
733
|
-
this.
|
734
|
-
} else {
|
745
|
+
_selectBasedOnQuery(event) {
|
746
|
+
if (this._shouldTreatAsNewOptionForFiltering(!isDeleteEvent(event))) {
|
747
|
+
this._selectNew();
|
748
|
+
} else if (isDeleteEvent(event)) {
|
749
|
+
this._deselect();
|
750
|
+
} else if (event.inputType === "hw:lockInSelection" && this._ensurableOption) {
|
751
|
+
this._selectAndAutocompleteMissingPortion(this._ensurableOption);
|
752
|
+
} else if (this._isOpen && this._visibleOptionElements[0]) {
|
753
|
+
this._selectAndAutocompleteMissingPortion(this._visibleOptionElements[0]);
|
754
|
+
} else if (this._isOpen) {
|
755
|
+
this._resetOptionsAndNotify();
|
735
756
|
this._markInvalid();
|
736
|
-
}
|
757
|
+
} else ;
|
737
758
|
}
|
738
759
|
|
739
|
-
|
740
|
-
|
760
|
+
_select(option, autocompleteStrategy) {
|
761
|
+
const previousValue = this._value;
|
741
762
|
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
}
|
763
|
+
this._resetOptionsSilently();
|
764
|
+
|
765
|
+
autocompleteStrategy(option);
|
746
766
|
|
747
|
-
this.
|
767
|
+
this._setValue(option.dataset.value);
|
768
|
+
this._markSelected(option);
|
769
|
+
this._markValid();
|
770
|
+
this._dispatchSelectionEvent({ isNewAndAllowed: false, previousValue: previousValue });
|
771
|
+
|
772
|
+
option.scrollIntoView({ block: "nearest" });
|
748
773
|
}
|
749
774
|
|
750
|
-
|
751
|
-
|
752
|
-
option.classList.toggle(this.selectedClass, selected);
|
753
|
-
}
|
775
|
+
_selectNew() {
|
776
|
+
const previousValue = this._value;
|
754
777
|
|
755
|
-
|
756
|
-
this.
|
778
|
+
this._resetOptionsSilently();
|
779
|
+
this._setValue(this._fullQuery);
|
780
|
+
this._setName(this.nameWhenNewValue);
|
781
|
+
this._markValid();
|
782
|
+
this._dispatchSelectionEvent({ isNewAndAllowed: true, previousValue: previousValue });
|
757
783
|
}
|
758
784
|
|
759
785
|
_deselect() {
|
760
|
-
const
|
786
|
+
const previousValue = this._value;
|
761
787
|
|
762
|
-
if (
|
788
|
+
if (this._selectedOptionElement) {
|
789
|
+
this._markNotSelected(this._selectedOptionElement);
|
790
|
+
}
|
763
791
|
|
764
|
-
this.
|
792
|
+
this._setValue(null);
|
765
793
|
this._setActiveDescendant("");
|
766
794
|
|
767
|
-
|
795
|
+
return previousValue
|
768
796
|
}
|
769
797
|
|
770
|
-
|
771
|
-
this.
|
772
|
-
this.
|
773
|
-
|
774
|
-
this._markValid();
|
798
|
+
_deselectAndNotify() {
|
799
|
+
const previousValue = this._deselect();
|
800
|
+
this._dispatchSelectionEvent({ isNewAndAllowed: false, previousValue: previousValue });
|
801
|
+
}
|
775
802
|
|
776
|
-
|
803
|
+
_forceSelectionAndFilter(option, event) {
|
804
|
+
this._forceSelectionWithoutFiltering(option);
|
805
|
+
this._filter(event);
|
806
|
+
}
|
807
|
+
|
808
|
+
_forceSelectionWithoutFiltering(option) {
|
809
|
+
this._selectAndReplaceFullQuery(option);
|
777
810
|
}
|
778
811
|
|
779
812
|
_selectIndex(index) {
|
780
813
|
const option = wrapAroundAccess(this._visibleOptionElements, index);
|
781
|
-
this.
|
814
|
+
this._forceSelectionWithoutFiltering(option);
|
782
815
|
}
|
783
816
|
|
784
817
|
_preselectOption() {
|
785
818
|
if (this._hasValueButNoSelection && this._allOptions.length < 100) {
|
786
819
|
const option = this._allOptions.find(option => {
|
787
|
-
return option.dataset.value === this.
|
820
|
+
return option.dataset.value === this._value
|
788
821
|
});
|
789
822
|
|
790
|
-
if (option) this._markSelected(option
|
823
|
+
if (option) this._markSelected(option);
|
791
824
|
}
|
792
825
|
}
|
793
826
|
|
827
|
+
_selectAndReplaceFullQuery(option) {
|
828
|
+
this._select(option, this._replaceFullQueryWithAutocompletedValue.bind(this));
|
829
|
+
}
|
830
|
+
|
831
|
+
_selectAndAutocompleteMissingPortion(option) {
|
832
|
+
this._select(option, this._autocompleteMissingPortion.bind(this));
|
833
|
+
}
|
834
|
+
|
794
835
|
_lockInSelection() {
|
795
836
|
if (this._shouldLockInSelection) {
|
796
|
-
this.
|
797
|
-
this.filter({ inputType: "hw:lockInSelection" });
|
837
|
+
this._forceSelectionAndFilter(this._ensurableOption, { inputType: "hw:lockInSelection" });
|
798
838
|
}
|
839
|
+
}
|
799
840
|
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
841
|
+
_markSelected(option) {
|
842
|
+
if (this.hasSelectedClass) option.classList.add(this.selectedClass);
|
843
|
+
option.setAttribute("aria-selected", true);
|
844
|
+
this._setActiveDescendant(option.id);
|
845
|
+
}
|
846
|
+
|
847
|
+
_markNotSelected(option) {
|
848
|
+
if (this.hasSelectedClass) option.classList.remove(this.selectedClass);
|
849
|
+
option.removeAttribute("aria-selected");
|
850
|
+
this._removeActiveDescendant();
|
804
851
|
}
|
805
852
|
|
806
853
|
_setActiveDescendant(id) {
|
807
854
|
this._forAllComboboxes(el => el.setAttribute("aria-activedescendant", id));
|
808
855
|
}
|
809
856
|
|
857
|
+
_removeActiveDescendant() {
|
858
|
+
this._setActiveDescendant("");
|
859
|
+
}
|
860
|
+
|
861
|
+
_setValue(value) {
|
862
|
+
this.hiddenFieldTarget.value = value;
|
863
|
+
}
|
864
|
+
|
865
|
+
_setName(value) {
|
866
|
+
this.hiddenFieldTarget.name = value;
|
867
|
+
}
|
868
|
+
|
869
|
+
get _value() {
|
870
|
+
return this.hiddenFieldTarget.value
|
871
|
+
}
|
872
|
+
|
810
873
|
get _hasValueButNoSelection() {
|
811
|
-
return this.
|
874
|
+
return this._value && !this._selectedOptionElement
|
812
875
|
}
|
813
876
|
|
814
877
|
get _shouldLockInSelection() {
|
@@ -1102,7 +1165,11 @@
|
|
1102
1165
|
close() {
|
1103
1166
|
if (this._isOpen) {
|
1104
1167
|
this._lockInSelection();
|
1168
|
+
this._clearInvalidQuery();
|
1169
|
+
|
1105
1170
|
this.expandedValue = false;
|
1171
|
+
|
1172
|
+
this._dispatchClosedEvent();
|
1106
1173
|
}
|
1107
1174
|
}
|
1108
1175
|
|
@@ -1171,6 +1238,8 @@
|
|
1171
1238
|
this._actingCombobox.setAttribute("aria-expanded", true); // needs to happen after setting acting combobox
|
1172
1239
|
}
|
1173
1240
|
|
1241
|
+
// +._collapse()+ differs from `.close()` in that it might be called by stimulus on connect because
|
1242
|
+
// it interprets a change in `expandedValue` — whereas `.close()` is only called internally by us.
|
1174
1243
|
_collapse() {
|
1175
1244
|
this._actingCombobox.setAttribute("aria-expanded", false); // needs to happen before resetting acting combobox
|
1176
1245
|
|
@@ -1211,6 +1280,13 @@
|
|
1211
1280
|
enableBodyScroll(this.dialogListboxTarget);
|
1212
1281
|
}
|
1213
1282
|
|
1283
|
+
_clearInvalidQuery() {
|
1284
|
+
if (this._isUnjustifiablyBlank) {
|
1285
|
+
this._deselect();
|
1286
|
+
this._clearQuery();
|
1287
|
+
}
|
1288
|
+
}
|
1289
|
+
|
1214
1290
|
get _isOpen() {
|
1215
1291
|
return this.expandedValue
|
1216
1292
|
}
|
@@ -1254,7 +1330,7 @@
|
|
1254
1330
|
// +_valueIsInvalid+ only checks if `comboboxTarget` (and not `_actingCombobox`) is required
|
1255
1331
|
// because the `required` attribute is only forwarded to the `comboboxTarget` element
|
1256
1332
|
get _valueIsInvalid() {
|
1257
|
-
const isRequiredAndEmpty = this.comboboxTarget.required && !this.
|
1333
|
+
const isRequiredAndEmpty = this.comboboxTarget.required && !this._value;
|
1258
1334
|
return isRequiredAndEmpty
|
1259
1335
|
}
|
1260
1336
|
};
|
@@ -1337,7 +1413,7 @@
|
|
1337
1413
|
|
1338
1414
|
if (inputType && inputType !== "hw:lockInSelection") {
|
1339
1415
|
if (delay) await sleep(delay);
|
1340
|
-
this.
|
1416
|
+
this._selectBasedOnQuery({ inputType });
|
1341
1417
|
} else {
|
1342
1418
|
this._preselectOption();
|
1343
1419
|
}
|
@@ -8,16 +8,18 @@ Combobox.Autocomplete = Base => class extends Base {
|
|
8
8
|
}
|
9
9
|
}
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
_replaceFullQueryWithAutocompletedValue(option) {
|
12
|
+
const autocompletedValue = option.getAttribute(this.autocompletableAttributeValue)
|
13
|
+
|
14
|
+
this._fullQuery = autocompletedValue
|
15
|
+
this._actingCombobox.setSelectionRange(autocompletedValue.length, autocompletedValue.length)
|
16
|
+
}
|
13
17
|
|
18
|
+
_autocompleteMissingPortion(option) {
|
14
19
|
const typedValue = this._typedQuery
|
15
20
|
const autocompletedValue = option.getAttribute(this.autocompletableAttributeValue)
|
16
21
|
|
17
|
-
if (
|
18
|
-
this._fullQuery = autocompletedValue
|
19
|
-
this._actingCombobox.setSelectionRange(autocompletedValue.length, autocompletedValue.length)
|
20
|
-
} else if (startsWith(autocompletedValue, typedValue)) {
|
22
|
+
if (this._autocompletesInline && startsWith(autocompletedValue, typedValue)) {
|
21
23
|
this._fullQuery = autocompletedValue
|
22
24
|
this._actingCombobox.setSelectionRange(typedValue.length, autocompletedValue.length)
|
23
25
|
}
|
@@ -2,16 +2,26 @@ import Combobox from "hw_combobox/models/combobox/base"
|
|
2
2
|
import { dispatch } from "hw_combobox/helpers"
|
3
3
|
|
4
4
|
Combobox.Events = Base => class extends Base {
|
5
|
-
_dispatchSelectionEvent({
|
6
|
-
|
7
|
-
|
5
|
+
_dispatchSelectionEvent({ isNewAndAllowed, previousValue }) {
|
6
|
+
if (previousValue !== this._value) {
|
7
|
+
dispatch("hw-combobox:selection", {
|
8
|
+
target: this.element,
|
9
|
+
detail: { ...this._eventableDetails, isNewAndAllowed, previousValue }
|
10
|
+
})
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
_dispatchClosedEvent() {
|
15
|
+
dispatch("hw-combobox:closed", { target: this.element, detail: this._eventableDetails })
|
16
|
+
}
|
17
|
+
|
18
|
+
get _eventableDetails() {
|
19
|
+
return {
|
20
|
+
value: this._value,
|
8
21
|
display: this._fullQuery,
|
9
22
|
query: this._typedQuery,
|
10
23
|
fieldName: this.hiddenFieldTarget.name,
|
11
|
-
isValid: this._valueIsValid
|
12
|
-
isNew: isNew
|
24
|
+
isValid: this._valueIsValid
|
13
25
|
}
|
14
|
-
|
15
|
-
dispatch("hw-combobox:selection", { target: this.element, detail })
|
16
26
|
}
|
17
27
|
}
|
@@ -1,23 +1,33 @@
|
|
1
1
|
|
2
2
|
import Combobox from "hw_combobox/models/combobox/base"
|
3
|
-
import { applyFilter, debounce,
|
3
|
+
import { applyFilter, debounce, unselectedPortion } from "hw_combobox/helpers"
|
4
4
|
import { get } from "hw_combobox/vendor/requestjs"
|
5
5
|
|
6
6
|
Combobox.Filtering = Base => class extends Base {
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
filterAndSelect(event) {
|
8
|
+
this._filter(event)
|
9
|
+
|
10
|
+
if (this._isSync) {
|
11
|
+
this._selectBasedOnQuery(event)
|
10
12
|
} else {
|
11
|
-
|
13
|
+
// noop, async selection is handled by stimulus callbacks
|
12
14
|
}
|
13
|
-
|
14
|
-
this._actingCombobox.toggleAttribute("data-queried", this._isQueried)
|
15
15
|
}
|
16
16
|
|
17
17
|
_initializeFiltering() {
|
18
18
|
this._debouncedFilterAsync = debounce(this._debouncedFilterAsync.bind(this))
|
19
19
|
}
|
20
20
|
|
21
|
+
_filter(event) {
|
22
|
+
if (this._isAsync) {
|
23
|
+
this._debouncedFilterAsync(event)
|
24
|
+
} else {
|
25
|
+
this._filterSync()
|
26
|
+
}
|
27
|
+
|
28
|
+
this._actingCombobox.toggleAttribute("data-queried", this._isQueried)
|
29
|
+
}
|
30
|
+
|
21
31
|
_debouncedFilterAsync(event) {
|
22
32
|
this._filterAsync(event)
|
23
33
|
}
|
@@ -32,27 +42,14 @@ Combobox.Filtering = Base => class extends Base {
|
|
32
42
|
await get(this.asyncSrcValue, { responseKind: "turbo-stream", query })
|
33
43
|
}
|
34
44
|
|
35
|
-
_filterSync(
|
45
|
+
_filterSync() {
|
36
46
|
this.open()
|
37
47
|
this._allOptionElements.forEach(applyFilter(this._fullQuery, { matching: this.filterableAttributeValue }))
|
38
|
-
this._commitFilter(event)
|
39
|
-
}
|
40
|
-
|
41
|
-
_commitFilter(event) {
|
42
|
-
if (this._shouldTreatAsNewOptionForFiltering(!isDeleteEvent(event))) {
|
43
|
-
this._selectNew()
|
44
|
-
} else if (isDeleteEvent(event)) {
|
45
|
-
this._deselect()
|
46
|
-
} else if (event.inputType === "hw:lockInSelection") {
|
47
|
-
this._select(this._ensurableOption)
|
48
|
-
} else if (this._isOpen) {
|
49
|
-
this._select(this._visibleOptionElements[0])
|
50
|
-
}
|
51
48
|
}
|
52
49
|
|
53
50
|
_clearQuery() {
|
54
51
|
this._fullQuery = ""
|
55
|
-
this.
|
52
|
+
this.filterAndSelect({ inputType: "deleteContentBackward" })
|
56
53
|
}
|
57
54
|
|
58
55
|
get _isQueried() {
|
@@ -2,9 +2,17 @@ import Combobox from "hw_combobox/models/combobox/base"
|
|
2
2
|
import { visible } from "hw_combobox/helpers"
|
3
3
|
|
4
4
|
Combobox.Options = Base => class extends Base {
|
5
|
-
|
6
|
-
this._deselect()
|
7
|
-
|
5
|
+
_resetOptionsSilently() {
|
6
|
+
this._resetOptions(this._deselect.bind(this))
|
7
|
+
}
|
8
|
+
|
9
|
+
_resetOptionsAndNotify() {
|
10
|
+
this._resetOptions(this._deselectAndNotify.bind(this))
|
11
|
+
}
|
12
|
+
|
13
|
+
_resetOptions(deselectionStrategy) {
|
14
|
+
this._setName(this.originalNameValue)
|
15
|
+
deselectionStrategy()
|
8
16
|
}
|
9
17
|
|
10
18
|
get _allowNew() {
|
@@ -32,7 +40,7 @@ Combobox.Options = Base => class extends Base {
|
|
32
40
|
}
|
33
41
|
|
34
42
|
get _isUnjustifiablyBlank() {
|
35
|
-
const valueIsMissing = !this.
|
43
|
+
const valueIsMissing = !this._value
|
36
44
|
const noBlankOptionSelected = !this._selectedOptionElement
|
37
45
|
|
38
46
|
return valueIsMissing && noBlankOptionSelected
|