@@ -38,14 +38,16 @@ function attachOneDropdownAria($dropdown) {
38
38
const listPopupRole = isComboBox ? 'listbox' : 'menu' ;
39
39
const listItemRole = isComboBox ? 'option' : 'menuitem' ;
40
40
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.
42
43
function prepareMenuItem ( $item ) {
43
44
if ( ! $item . attr ( 'id' ) ) $item . attr ( 'id' , generateAriaId ( ) ) ;
44
45
$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' ) ;
46
47
}
47
48
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)
49
51
const dropdownTemplates = { ...$dropdown . dropdown ( 'setting' , 'templates' ) } ;
50
52
const dropdownTemplatesMenuOld = dropdownTemplates . menu ;
51
53
dropdownTemplates . menu = function ( response , fields , preserveHTML , className ) {
@@ -92,12 +94,11 @@ function attachOneDropdownAria($dropdown) {
92
94
// if there is an active item, use it (the user is navigating between items)
93
95
// otherwise use the "selected" for combobox (for the last selected item)
94
96
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 ) {
99
99
$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
101
102
$focusable . removeAttr ( 'aria-activedescendant' ) ;
102
103
$active . removeClass ( 'active' ) . removeClass ( 'selected' ) ;
103
104
}
@@ -116,7 +117,9 @@ function attachOneDropdownAria($dropdown) {
116
117
117
118
// use setTimeout to run the refreshAria in next tick (to make sure the Fomantic UI code has finished its work)
118
119
// 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 ) } ;
120
123
$dropdown . on ( 'keyup' , ( e ) => { if ( e . key . startsWith ( 'Arrow' ) ) deferredRefreshAria ( ) ; } ) ;
121
124
122
125
// if the dropdown has been opened by focus, do not trigger the next click event again.
@@ -142,14 +145,14 @@ function attachOneDropdownAria($dropdown) {
142
145
$dropdown [ 0 ] . addEventListener ( 'blur' , ( e ) => {
143
146
debug ( e . type ) ;
144
147
ignoreClickPreVisible = ignoreClickPreEvents = 0 ;
145
- deferredRefreshAria ( ) ;
148
+ deferredRefreshAria ( 100 ) ;
146
149
} , true ) ;
147
150
$dropdown [ 0 ] . addEventListener ( 'mouseup' , ( e ) => {
148
151
debug ( e . type ) ;
149
152
setTimeout ( ( ) => {
150
153
debug ( `${ e . type } (deferred)` ) ;
151
154
ignoreClickPreVisible = ignoreClickPreEvents = 0 ;
152
- deferredRefreshAria ( ) ;
155
+ deferredRefreshAria ( 100 ) ;
153
156
} , 0 ) ;
154
157
} , true ) ;
155
158
$dropdown [ 0 ] . addEventListener ( 'click' , ( e ) => {
0 commit comments