Skip to content

Commit 9bad02d

Browse files
committed
add more comments, and use a small delay to avoid UI lag (due to Fomantic UI animation)
1 parent 696a120 commit 9bad02d

File tree

1 file changed

+14
-11
lines changed

1 file changed

+14
-11
lines changed

web_src/js/features/aria.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)