@@ -15,6 +15,7 @@ import {
15
15
defineJQueryPlugin ,
16
16
getNextActiveElement ,
17
17
getElement ,
18
+ getUID ,
18
19
isVisible ,
19
20
isRTL
20
21
} from './util/index.js'
@@ -86,10 +87,12 @@ const CLASS_NAME_TAG_DELETE = 'form-multi-select-tag-delete'
86
87
const Default = {
87
88
allowList : DefaultAllowlist ,
88
89
ariaCleanerLabel : 'Clear all selections' ,
90
+ ariaIndicatorLabel : 'Toggle visibility of options menu' ,
89
91
cleaner : true ,
90
92
clearSearchOnSelect : false ,
91
93
container : false ,
92
94
disabled : false ,
95
+ id : null ,
93
96
invalid : false ,
94
97
multiple : true ,
95
98
name : null ,
@@ -115,10 +118,12 @@ const Default = {
115
118
const DefaultType = {
116
119
allowList : 'object' ,
117
120
ariaCleanerLabel : 'string' ,
121
+ ariaIndicatorLabel : 'string' ,
118
122
cleaner : 'boolean' ,
119
123
clearSearchOnSelect : 'boolean' ,
120
124
container : '(string|element|boolean)' ,
121
125
disabled : 'boolean' ,
126
+ id : '(string|null)' ,
122
127
invalid : 'boolean' ,
123
128
multiple : 'boolean' ,
124
129
name : '(string|null)' ,
@@ -151,6 +156,8 @@ class MultiSelect extends BaseComponent {
151
156
constructor ( element , config ) {
152
157
super ( element , config )
153
158
159
+ this . _uniqueId = this . _config . id || this . _element . id || getUID ( `${ this . constructor . NAME } ` )
160
+ this . _uniqueName = this . _config . name || this . _element . name || this . _uniqueId
154
161
this . _configureNativeSelect ( )
155
162
this . _indicatorElement = null
156
163
this . _selectAllElement = null
@@ -542,7 +549,10 @@ class MultiSelect extends BaseComponent {
542
549
multiSelectEl . classList . add ( CLASS_NAME_SELECT )
543
550
multiSelectEl . classList . toggle ( 'is-invalid' , this . _config . invalid )
544
551
multiSelectEl . classList . toggle ( 'is-valid' , this . _config . valid )
552
+ multiSelectEl . role = 'combobox'
545
553
multiSelectEl . setAttribute ( 'aria-expanded' , 'false' )
554
+ multiSelectEl . setAttribute ( 'aria-haspopup' , 'listbox' )
555
+ multiSelectEl . setAttribute ( 'aria-owns' , `${ this . _uniqueId } -listbox` )
546
556
547
557
if ( this . _config . disabled ) {
548
558
this . _element . classList . add ( CLASS_NAME_DISABLED )
@@ -562,9 +572,8 @@ class MultiSelect extends BaseComponent {
562
572
this . _updateSearch ( )
563
573
}
564
574
565
- if ( this . _config . name || this . _element . id || this . _element . name ) {
566
- this . _element . setAttribute ( 'name' , ( this . _config . name || this . _element . name || `multi-select-${ this . _element . id } ` ) )
567
- }
575
+ this . _element . setAttribute ( 'id' , this . _uniqueId )
576
+ this . _element . setAttribute ( 'name' , this . _uniqueName )
568
577
569
578
this . _createOptionsContainer ( )
570
579
this . _hideNativeSelect ( )
@@ -612,6 +621,7 @@ class MultiSelect extends BaseComponent {
612
621
const indicator = document . createElement ( 'button' )
613
622
indicator . type = 'button'
614
623
indicator . classList . add ( 'form-multi-select-indicator' )
624
+ indicator . setAttribute ( 'aria-label' , this . _config . ariaIndicatorLabel )
615
625
616
626
if ( this . _config . disabled ) {
617
627
indicator . tabIndex = - 1
@@ -656,6 +666,9 @@ class MultiSelect extends BaseComponent {
656
666
input . disabled = true
657
667
}
658
668
669
+ input . setAttribute ( 'id' , `search-${ this . _uniqueId } ` )
670
+ input . setAttribute ( 'name' , `search-${ this . _uniqueName } ` )
671
+
659
672
this . _searchElement = input
660
673
this . _updateSearchSize ( )
661
674
@@ -665,6 +678,12 @@ class MultiSelect extends BaseComponent {
665
678
_createOptionsContainer ( ) {
666
679
const dropdownDiv = document . createElement ( 'div' )
667
680
dropdownDiv . classList . add ( CLASS_NAME_SELECT_DROPDOWN )
681
+ dropdownDiv . role = 'listbox'
682
+ dropdownDiv . setAttribute ( 'id' , `${ this . _uniqueId } -listbox` )
683
+
684
+ if ( this . _config . multiple ) {
685
+ dropdownDiv . setAttribute ( 'aria-multiselectable' , 'true' )
686
+ }
668
687
669
688
if ( this . _config . selectAll && this . _config . multiple ) {
670
689
const selectAllButton = document . createElement ( 'button' )
@@ -715,6 +734,7 @@ class MultiSelect extends BaseComponent {
715
734
716
735
optionDiv . dataset . value = String ( option . value )
717
736
optionDiv . tabIndex = 0
737
+ optionDiv . role = 'option'
718
738
719
739
if ( this . _config . optionsTemplate && typeof this . _config . optionsTemplate === 'function' ) {
720
740
optionDiv . innerHTML = this . _config . sanitize ?
@@ -851,6 +871,7 @@ class MultiSelect extends BaseComponent {
851
871
const option = SelectorEngine . findOne ( `[data-value="${ value } "]` , this . _optionsElement )
852
872
if ( option ) {
853
873
option . classList . add ( CLASS_NAME_SELECTED )
874
+ option . setAttribute ( 'aria-selected' , 'true' )
854
875
}
855
876
856
877
EventHandler . trigger ( this . _element , EVENT_CHANGED , {
@@ -871,6 +892,7 @@ class MultiSelect extends BaseComponent {
871
892
const option = SelectorEngine . findOne ( `[data-value="${ value } "]` , this . _optionsElement )
872
893
if ( option ) {
873
894
option . classList . remove ( CLASS_NAME_SELECTED )
895
+ option . setAttribute ( 'aria-selected' , 'false' )
874
896
}
875
897
876
898
EventHandler . trigger ( this . _element , EVENT_CHANGED , {
0 commit comments