|
1 | 1 | /*! |
2 | | - * Virtual Select v1.1.2 |
| 2 | + * Virtual Select v1.1.3 |
3 | 3 | * https://sa-si-dev.github.io/virtual-select |
4 | 4 | * Licensed under MIT (https://github.com/sa-si-dev/virtual-select/blob/master/LICENSE) |
5 | 5 | *//******/ (function() { // webpackBootstrap |
@@ -808,7 +808,7 @@ var VirtualSelect = /*#__PURE__*/function () { |
808 | 808 | } |
809 | 809 |
|
810 | 810 | // eslint-disable-next-line no-trailing-spaces |
811 | | - var html = "<div id=\"vscomp-dropbox-container-".concat(this.uniqueId, "\" role=\"listbox\" class=\"").concat(dropboxContainerClasses, "\">\n <div class=\"vscomp-dropbox-container-top\" aria-hidden=\"true\" tabindex=\"-1\"> </div>\n <div class=\"").concat(dropboxClasses, "\">\n <div class=\"vscomp-search-wrapper\"></div>\n\n <div class=\"vscomp-options-container\">\n <div class=\"vscomp-options-loader\"></div>\n\n <div class=\"vscomp-options-list\">\n <div class=\"vscomp-options\"></div>\n </div>\n </div>\n\n <div class=\"vscomp-options-bottom-freezer\"></div>\n <div class=\"vscomp-no-options\">").concat(this.noOptionsText, "</div>\n <div class=\"vscomp-no-search-results\">").concat(this.noSearchResultsText, "</div>\n\n <span class=\"vscomp-dropbox-close-button\"><i class=\"vscomp-clear-icon\"></i></span>\n </div>\n <div class=\"vscomp-dropbox-container-bottom\" aria-hidden=\"true\" tabindex=\"-1\"> </div>\n </div>"); |
| 811 | + var html = "<div id=\"vscomp-dropbox-container-".concat(this.uniqueId, "\" class=\"").concat(dropboxContainerClasses, "\">\n <div class=\"vscomp-dropbox-container-top\" aria-hidden=\"true\" tabindex=\"-1\"> </div>\n <div class=\"").concat(dropboxClasses, "\">\n <div class=\"vscomp-search-wrapper\"></div>\n\n <div class=\"vscomp-options-container\" role=\"listbox\" aria-labelledby=\"vscomp-ele-wrapper-").concat(this.uniqueId, "\" >\n <div class=\"vscomp-options-loader\"></div>\n\n <div class=\"vscomp-options-list\">\n <div class=\"vscomp-options\"></div>\n </div>\n </div>\n\n <div class=\"vscomp-options-bottom-freezer\"></div>\n <div class=\"vscomp-no-options\">").concat(this.noOptionsText, "</div>\n <div class=\"vscomp-no-search-results\">").concat(this.noSearchResultsText, "</div>\n\n <span class=\"vscomp-dropbox-close-button\"><i class=\"vscomp-clear-icon\"></i></span>\n </div>\n <div class=\"vscomp-dropbox-container-bottom\" aria-hidden=\"true\" tabindex=\"-1\"> </div>\n </div>"); |
812 | 812 | if ($wrapper) { |
813 | 813 | var $dropboxWrapper = document.createElement('div'); |
814 | 814 | this.$dropboxWrapper = $dropboxWrapper; |
@@ -2329,13 +2329,28 @@ var VirtualSelect = /*#__PURE__*/function () { |
2329 | 2329 | this.visibleOptionsCount = visibleOptionsCount; |
2330 | 2330 | this.afterSetVisibleOptionsCount(); |
2331 | 2331 | } |
| 2332 | + |
| 2333 | + /** |
| 2334 | + * Calculates ARIA metadata (aria-setsize and aria-posinset) for virtualized listbox accessibility. |
| 2335 | + * This method iterates through ALL filtered options (not just rendered ones) to calculate |
| 2336 | + * the correct position in the full filtered set. This ensures screen readers announce |
| 2337 | + * correct positions even when only a subset of options is rendered (e.g., "Option 50, 50 of 10001"). |
| 2338 | + * |
| 2339 | + * Example: With 10,001 filtered options showing only 5 at a time: |
| 2340 | + * - All 10,001 options get filteredIndex values: 1, 2, 3, ..., 10001 |
| 2341 | + * - ariaSetSize = 10001 |
| 2342 | + * - When options 50-54 are rendered, they have filteredIndex: 50, 51, 52, 53, 54 |
| 2343 | + * - Screen reader announces: "Option 50, 50 of 10001" |
| 2344 | + */ |
2332 | 2345 | }, { |
2333 | 2346 | key: "calculateAriaMetadata", |
2334 | 2347 | value: function calculateAriaMetadata() { |
2335 | 2348 | var _this10 = this; |
2336 | 2349 | var ariaSetSize = 0; |
2337 | 2350 | var filteredPosition = 0; |
2338 | 2351 | var optionsSource = this.sortedOptions && this.sortedOptions.length ? this.sortedOptions : this.options; |
| 2352 | + |
| 2353 | + // Iterate through ALL options (not just rendered ones) to calculate positions in the full filtered set |
2339 | 2354 | optionsSource.forEach(function (d) { |
2340 | 2355 | if (d.isCurrentNew) { |
2341 | 2356 | // eslint-disable-next-line no-param-reassign |
@@ -2971,6 +2986,8 @@ var VirtualSelect = /*#__PURE__*/function () { |
2971 | 2986 | DomUtils.dispatchEvent(this.$ele, 'beforeClose'); |
2972 | 2987 | DomUtils.setAria(this.$wrapper, 'expanded', false); |
2973 | 2988 | DomUtils.setAria(this.$wrapper, 'activedescendant', ''); |
| 2989 | + // Also clear aria-activedescendant on the listbox container |
| 2990 | + DomUtils.setAria(this.$dropboxContainer, 'activedescendant', ''); |
2974 | 2991 | } |
2975 | 2992 | if (this.dropboxPopover && !isSilent) { |
2976 | 2993 | this.dropboxPopover.hide(); |
@@ -3764,6 +3781,8 @@ var VirtualSelect = /*#__PURE__*/function () { |
3764 | 3781 | } |
3765 | 3782 | if (isFocused) { |
3766 | 3783 | DomUtils.setAria(this.$wrapper, 'activedescendant', $ele.id); |
| 3784 | + // Also set aria-activedescendant on the listbox container for better screen reader support |
| 3785 | + DomUtils.setAria(this.$dropboxContainer, 'activedescendant', $ele.id); |
3767 | 3786 | } |
3768 | 3787 | } |
3769 | 3788 |
|
|
0 commit comments