@@ -15,6 +15,7 @@ import {
1515 defineJQueryPlugin ,
1616 getNextActiveElement ,
1717 getElement ,
18+ getUID ,
1819 isVisible ,
1920 isRTL
2021} from './util/index.js'
@@ -86,10 +87,12 @@ const CLASS_NAME_TAG_DELETE = 'form-multi-select-tag-delete'
8687const Default = {
8788 allowList : DefaultAllowlist ,
8889 ariaCleanerLabel : 'Clear all selections' ,
90+ ariaIndicatorLabel : 'Toggle visibility of options menu' ,
8991 cleaner : true ,
9092 clearSearchOnSelect : false ,
9193 container : false ,
9294 disabled : false ,
95+ id : null ,
9396 invalid : false ,
9497 multiple : true ,
9598 name : null ,
@@ -115,10 +118,12 @@ const Default = {
115118const DefaultType = {
116119 allowList : 'object' ,
117120 ariaCleanerLabel : 'string' ,
121+ ariaIndicatorLabel : 'string' ,
118122 cleaner : 'boolean' ,
119123 clearSearchOnSelect : 'boolean' ,
120124 container : '(string|element|boolean)' ,
121125 disabled : 'boolean' ,
126+ id : '(string|null)' ,
122127 invalid : 'boolean' ,
123128 multiple : 'boolean' ,
124129 name : '(string|null)' ,
@@ -151,6 +156,8 @@ class MultiSelect extends BaseComponent {
151156 constructor ( element , config ) {
152157 super ( element , config )
153158
159+ this . _uniqueId = this . _config . id || this . _element . id || getUID ( `${ this . constructor . NAME } ` )
160+ this . _uniqueName = this . _config . name || this . _element . name || this . _uniqueId
154161 this . _configureNativeSelect ( )
155162 this . _indicatorElement = null
156163 this . _selectAllElement = null
@@ -542,7 +549,10 @@ class MultiSelect extends BaseComponent {
542549 multiSelectEl . classList . add ( CLASS_NAME_SELECT )
543550 multiSelectEl . classList . toggle ( 'is-invalid' , this . _config . invalid )
544551 multiSelectEl . classList . toggle ( 'is-valid' , this . _config . valid )
552+ multiSelectEl . role = 'combobox'
545553 multiSelectEl . setAttribute ( 'aria-expanded' , 'false' )
554+ multiSelectEl . setAttribute ( 'aria-haspopup' , 'listbox' )
555+ multiSelectEl . setAttribute ( 'aria-owns' , `${ this . _uniqueId } -listbox` )
546556
547557 if ( this . _config . disabled ) {
548558 this . _element . classList . add ( CLASS_NAME_DISABLED )
@@ -562,9 +572,8 @@ class MultiSelect extends BaseComponent {
562572 this . _updateSearch ( )
563573 }
564574
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 )
568577
569578 this . _createOptionsContainer ( )
570579 this . _hideNativeSelect ( )
@@ -612,6 +621,7 @@ class MultiSelect extends BaseComponent {
612621 const indicator = document . createElement ( 'button' )
613622 indicator . type = 'button'
614623 indicator . classList . add ( 'form-multi-select-indicator' )
624+ indicator . setAttribute ( 'aria-label' , this . _config . ariaIndicatorLabel )
615625
616626 if ( this . _config . disabled ) {
617627 indicator . tabIndex = - 1
@@ -656,6 +666,9 @@ class MultiSelect extends BaseComponent {
656666 input . disabled = true
657667 }
658668
669+ input . setAttribute ( 'id' , `search-${ this . _uniqueId } ` )
670+ input . setAttribute ( 'name' , `search-${ this . _uniqueName } ` )
671+
659672 this . _searchElement = input
660673 this . _updateSearchSize ( )
661674
@@ -665,6 +678,12 @@ class MultiSelect extends BaseComponent {
665678 _createOptionsContainer ( ) {
666679 const dropdownDiv = document . createElement ( 'div' )
667680 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+ }
668687
669688 if ( this . _config . selectAll && this . _config . multiple ) {
670689 const selectAllButton = document . createElement ( 'button' )
@@ -715,6 +734,7 @@ class MultiSelect extends BaseComponent {
715734
716735 optionDiv . dataset . value = String ( option . value )
717736 optionDiv . tabIndex = 0
737+ optionDiv . role = 'option'
718738
719739 if ( this . _config . optionsTemplate && typeof this . _config . optionsTemplate === 'function' ) {
720740 optionDiv . innerHTML = this . _config . sanitize ?
@@ -851,6 +871,7 @@ class MultiSelect extends BaseComponent {
851871 const option = SelectorEngine . findOne ( `[data-value="${ value } "]` , this . _optionsElement )
852872 if ( option ) {
853873 option . classList . add ( CLASS_NAME_SELECTED )
874+ option . setAttribute ( 'aria-selected' , 'true' )
854875 }
855876
856877 EventHandler . trigger ( this . _element , EVENT_CHANGED , {
@@ -871,6 +892,7 @@ class MultiSelect extends BaseComponent {
871892 const option = SelectorEngine . findOne ( `[data-value="${ value } "]` , this . _optionsElement )
872893 if ( option ) {
873894 option . classList . remove ( CLASS_NAME_SELECTED )
895+ option . setAttribute ( 'aria-selected' , 'false' )
874896 }
875897
876898 EventHandler . trigger ( this . _element , EVENT_CHANGED , {
0 commit comments