@@ -38,14 +38,16 @@ function attachOneDropdownAria($dropdown) {
3838 const listPopupRole = isComboBox ? 'listbox' : 'menu' ;
3939 const listItemRole = isComboBox ? 'option' : 'menuitem' ;
4040
41- // make the item has role=option/menuitem, and add an id if there wasn't one yet.
41+ // make the item has role=option/menuitem, add an id if there wasn't one yet, make items as non-focusable
42+ // the elements inside the dropdown menu item should not be focusable, the focus should always be on the dropdown primary element.
4243 function prepareMenuItem ( $item ) {
4344 if ( ! $item . attr ( 'id' ) ) $item . attr ( 'id' , generateAriaId ( ) ) ;
4445 $item . attr ( { 'role' : listItemRole , 'tabindex' : '-1' } ) ;
45- $item . find ( 'a' ) . attr ( 'tabindex' , '-1' ) ; // as above, the elements inside the dropdown menu item should not be focusable, the focus should always be on the dropdown primary element.
46+ $item . find ( 'a' ) . attr ( 'tabindex' , '-1' ) ;
4647 }
4748
48- // delegate the dropdown's template function to add aria attributes
49+ // delegate the dropdown's template function to add aria attributes.
50+ // the "template" functions are used for dynamic creation (eg: AJAX)
4951 const dropdownTemplates = { ...$dropdown . dropdown ( 'setting' , 'templates' ) } ;
5052 const dropdownTemplatesMenuOld = dropdownTemplates . menu ;
5153 dropdownTemplates . menu = function ( response , fields , preserveHTML , className ) {
@@ -92,12 +94,11 @@ function attachOneDropdownAria($dropdown) {
9294 // if there is an active item, use it (the user is navigating between items)
9395 // otherwise use the "selected" for combobox (for the last selected item)
9496 const $active = $menu . find ( '> .item.active, > .item.selected' ) ;
95-
96- // if there is an active item, use its id. if no active item or the dropdown is used as menu and is hidden, empty the active item
97- const activeId = $active . attr ( 'id' ) ;
98- if ( menuVisible && activeId ) {
97+ // if the popup is visible and has an active/selected item, use its id as aria-activedescendant
98+ if ( menuVisible ) {
9999 $focusable . attr ( 'aria-activedescendant' , $active . attr ( 'id' ) ) ;
100- } else if ( ! isComboBox && ! menuVisible ) {
100+ } else if ( ! isComboBox ) {
101+ // for menu, when the popup is hidden, no need to keep the aria-activedescendant, and clear the active/selected item
101102 $focusable . removeAttr ( 'aria-activedescendant' ) ;
102103 $active . removeClass ( 'active' ) . removeClass ( 'selected' ) ;
103104 }
@@ -116,7 +117,9 @@ function attachOneDropdownAria($dropdown) {
116117
117118 // use setTimeout to run the refreshAria in next tick (to make sure the Fomantic UI code has finished its work)
118119 // do not return any value, jQuery has return-value related behaviors.
119- const deferredRefreshAria = ( ) => { setTimeout ( refreshAria , 0 ) } ;
120+ // when the popup is hiding, it's better to have a small "delay", because there is a Fomantic UI animation
121+ // without the delay for hiding, the UI will be somewhat laggy and sometimes may get stuck in the animation.
122+ const deferredRefreshAria = ( delay = 0 ) => { setTimeout ( refreshAria , delay ) } ;
120123 $dropdown . on ( 'keyup' , ( e ) => { if ( e . key . startsWith ( 'Arrow' ) ) deferredRefreshAria ( ) ; } ) ;
121124
122125 // if the dropdown has been opened by focus, do not trigger the next click event again.
@@ -142,14 +145,14 @@ function attachOneDropdownAria($dropdown) {
142145 $dropdown [ 0 ] . addEventListener ( 'blur' , ( e ) => {
143146 debug ( e . type ) ;
144147 ignoreClickPreVisible = ignoreClickPreEvents = 0 ;
145- deferredRefreshAria ( ) ;
148+ deferredRefreshAria ( 100 ) ;
146149 } , true ) ;
147150 $dropdown [ 0 ] . addEventListener ( 'mouseup' , ( e ) => {
148151 debug ( e . type ) ;
149152 setTimeout ( ( ) => {
150153 debug ( `${ e . type } (deferred)` ) ;
151154 ignoreClickPreVisible = ignoreClickPreEvents = 0 ;
152- deferredRefreshAria ( ) ;
155+ deferredRefreshAria ( 100 ) ;
153156 } , 0 ) ;
154157 } , true ) ;
155158 $dropdown [ 0 ] . addEventListener ( 'click' , ( e ) => {
0 commit comments