// Shared pager accessibility helpers for PublicModule grids (function () { function enhancePagerDropdownAccessibility() { const grid = $('.table_grid').data('kendoGrid'); if (!grid) { return; } const $gridWrapper = grid.wrapper || grid.element || $('.table_grid'); setTimeout(function () { $gridWrapper .find('.k-pager-wrap .k-link, .k-pager-numbers li a.k-link') .attr('tabindex', 0); const dropdown = $gridWrapper .find('.k-pager-sizes select') .data('kendoDropDownList'); if (!dropdown) { return; } const $wrapper = dropdown.wrapper; const gridElementId = (grid.element && grid.element.attr && grid.element.attr('id')) || grid._uid || 'default'; const liveRegionId = 'pager-dropdown-live-region-' + gridElementId; let $liveRegion = $gridWrapper.find('#' + liveRegionId); if ($liveRegion.length === 0) { $liveRegion = $('') .attr('id', liveRegionId) .attr('aria-live', 'assertive') .attr('aria-atomic', 'true') .addClass('sr-only') .css({ position: 'absolute', left: '-9999px', width: '1px', height: '1px', overflow: 'hidden' }); $wrapper.after($liveRegion); } const announceFocusedItem = function () { let itemToAnnounce = dropdown.ul.find('.k-state-focused'); if (itemToAnnounce.length === 0) { itemToAnnounce = dropdown.ul.find('.k-state-selected'); } if (itemToAnnounce.length > 0) { const text = itemToAnnounce.text().trim(); $liveRegion.text(text + ' items per page'); } }; const announceDropdownOpened = function () { const selectedItem = dropdown.ul.find('.k-state-selected'); if (selectedItem.length > 0) { const text = selectedItem.text().trim(); $liveRegion.text(text + ' selected'); } }; const announcePageSize = function (pageSize) { $liveRegion.text('Showing ' + pageSize + ' items per page'); }; const pagerDropdown = $wrapper[0]; // Remove any previous capture handler if present if (pagerDropdown && pagerDropdown._pagerArrowDownCapture) { try { pagerDropdown.removeEventListener('keydown', pagerDropdown._pagerArrowDownCapture, true); } catch (e) {} } pagerDropdown._pagerArrowDownCapture = function (e) { const isOpen = dropdown.popup.visible(); if (e.key === 'ArrowDown' && !isOpen) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); dropdown.open(); } }; pagerDropdown.addEventListener('keydown', pagerDropdown._pagerArrowDownCapture, true); const updateAriaLabel = function () { const currentValue = dropdown.value(); $wrapper.attr('aria-label', 'Items per page, ' + currentValue); }; $wrapper.attr({ tabindex: 0, 'aria-haspopup': 'listbox', 'aria-expanded': 'false', 'aria-label': 'Items per page' }); updateAriaLabel(); $wrapper.off('keydown.accessibility'); $wrapper.on('keydown.accessibility', function (e) { const isOpen = dropdown.popup.visible(); switch (e.key) { case 'Enter': e.preventDefault(); if (!isOpen) { dropdown.open(); } break; case ' ': e.preventDefault(); if (isOpen) { const pageSize = dropdown.value(); grid.dataSource.pageSize(parseInt(pageSize, 10)); announcePageSize(pageSize); updateAriaLabel(); dropdown.close(); $wrapper.focus(); } else { dropdown.open(); } break; case 'ArrowDown': if (isOpen) { setTimeout(announceFocusedItem, 50); } break; case 'ArrowUp': if (e.altKey && isOpen) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); const pageSize = dropdown.value(); grid.dataSource.pageSize(parseInt(pageSize, 10)); announcePageSize(pageSize); updateAriaLabel(); dropdown.close(); $wrapper.focus(); return; } e.preventDefault(); if (!isOpen) { dropdown.open(); setTimeout(function () { dropdown.select(0); }, 0); } else { setTimeout(announceFocusedItem, 50); } break; case 'Home': e.preventDefault(); if (!isOpen) { dropdown.open(); } else { setTimeout(announceFocusedItem, 50); } break; case 'End': e.preventDefault(); if (!isOpen) { dropdown.open(); } else { setTimeout(announceFocusedItem, 50); } break; case 'Escape': if (isOpen) { e.preventDefault(); e.stopPropagation(); dropdown.close(); } break; } }); const handleOpen = function () { $wrapper.attr('aria-expanded', 'true'); dropdown.ul.closest('.k-list-container').attr({ role: 'listbox', 'aria-label': 'Page size options' }); dropdown.ul.find('li').each(function () { const $item = $(this); $item.attr('role', 'option'); const isSelected = $item.hasClass('k-state-selected'); $item.attr('aria-selected', isSelected ? 'true' : 'false'); }); setTimeout(announceDropdownOpened, 100); }; const handleClose = function () { $wrapper.attr('aria-expanded', 'false'); setTimeout(() => $wrapper.focus(), 0); }; const handleChange = function () { const pageSize = dropdown.value(); if (pageSize) { announcePageSize(pageSize); updateAriaLabel(); } }; dropdown.unbind('open', handleOpen); dropdown.bind('open', handleOpen); dropdown.unbind('close', handleClose); dropdown.bind('close', handleClose); dropdown.unbind('change', handleChange); dropdown.bind('change', handleChange); const initialPageSize = dropdown.value(); if (initialPageSize) { setTimeout(() => announcePageSize(initialPageSize), 300); } }, 150); } // Expose on window so views can call it without bundling changes window.afPagerAccessibility = window.afPagerAccessibility || {}; window.afPagerAccessibility.enhancePagerDropdownAccessibility = enhancePagerDropdownAccessibility; })();