diff --git a/lib/templates/local/comboboxsearch/resultset.mustache b/lib/templates/local/comboboxsearch/resultset.mustache
index 27133d9d8f8..4a9f1ef2d06 100644
--- a/lib/templates/local/comboboxsearch/resultset.mustache
+++ b/lib/templates/local/comboboxsearch/resultset.mustache
@@ -41,7 +41,7 @@
}
}}
-
+
{{#hasresults}}
{{$results}}
{{#results}}
diff --git a/theme/boost/amd/build/aria.min.js b/theme/boost/amd/build/aria.min.js
index 677391beb29..7098ec29adf 100644
--- a/theme/boost/amd/build/aria.min.js
+++ b/theme/boost/amd/build/aria.min.js
@@ -1,10 +1,10 @@
-define("theme_boost/aria",["exports","jquery","core/pending"],(function(_exports,_jquery,_pending){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+define("theme_boost/aria",["exports","jquery","core/pending","core/local/aria/focuslock"],(function(_exports,_jquery,_pending,FocusLockManager){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Enhancements to Bootstrap components for accessibility.
*
* @module theme_boost/aria
* @copyright 2018 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_pending=_interopRequireDefault(_pending);const dropdownFix=()=>{let focusEnd=!1;const setFocusEnd=function(){let end=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];focusEnd=end},shiftFocus=function(element){let focusCheck=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;const pendingPromise=new _pending.default("core/aria:delayed-focus");setTimeout((()=>{focusCheck&&!focusCheck()||element.focus(),pendingPromise.resolve()}),50)},handleMenuButton=e=>{const trigger=e.key;let fixFocus=!1;if(" "!==trigger&&"Enter"!==trigger||(fixFocus=!0,e.preventDefault(),e.target.click()),"ArrowUp"!==trigger&&"ArrowDown"!==trigger||(fixFocus=!0),!fixFocus)return;const menu=e.target.parentElement.querySelector('[role="menu"]');let menuItems=!1,foundMenuItem=!1,textInput=!1;menu&&(menuItems=menu.querySelectorAll('[role="menuitem"]'),textInput=e.target.parentElement.querySelector('[data-action="search"]')),menuItems&&menuItems.length>0&&("ArrowUp"===trigger?setFocusEnd():setFocusEnd(!1),foundMenuItem=(()=>{const result=focusEnd;return focusEnd=!1,result})()?menuItems[menuItems.length-1]:menuItems[0]),textInput&&shiftFocus(textInput),foundMenuItem&&null===textInput&&shiftFocus(foundMenuItem)};document.addEventListener("keypress",(e=>{if(e.target.matches('.dropdown [role="menu"] [role="menuitem"]')){const menu=e.target.closest('[role="menu"]');if(!menu)return;const menuItems=menu.querySelectorAll('[role="menuitem"]');if(!menuItems)return;const trigger=e.key.toLowerCase();for(let i=0;i{if(e.target.matches('[data-toggle="dropdown"]')&&handleMenuButton(e),e.target.matches('.dropdown [role="menu"] [role="menuitem"]')){const trigger=e.key;let next=!1;const menu=e.target.closest('[role="menu"]');if(!menu)return;const menuItems=menu.querySelectorAll('[role="menuitem"]');if(!menuItems)return;if("ArrowDown"==trigger){for(let i=0;i{const trigger=e.target.querySelector('[data-toggle="dropdown"]'),focused=document.activeElement!=document.body?document.activeElement:null;trigger&&focused&&e.target.contains(focused)&&shiftFocus(trigger,(()=>document.activeElement===document.body||e.target.contains(document.activeElement)))}))},tabElementFix=()=>{document.addEventListener("keydown",(e=>{["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Home","End"].includes(e.key)&&e.target.matches('[role="tablist"] [role="tab"]')&&(e=>{const tabList=e.target.closest('[role="tablist"]'),vertical="vertical"==tabList.getAttribute("aria-orientation"),rtl=window.right_to_left(),arrowNext=vertical?"ArrowDown":rtl?"ArrowLeft":"ArrowRight",arrowPrevious=vertical?"ArrowUp":rtl?"ArrowRight":"ArrowLeft",tabs=Array.prototype.filter.call(tabList.querySelectorAll('[role="tab"]'),(tab=>!!tab.offsetHeight));for(let i=0;i{if(e.target.matches('[role="tablist"] [data-toggle="tab"], [role="tablist"] [data-toggle="pill"]')){const tabs=e.target.closest('[role="tablist"]').querySelectorAll('[data-toggle="tab"], [data-toggle="pill"]');e.preventDefault(),(0,_jquery.default)(e.target).tab("show"),tabs.forEach((tab=>{tab.tabIndex=-1})),e.target.tabIndex=0}}))};_exports.init=()=>{dropdownFix(),(()=>{(0,_jquery.default)(document).on("show.bs.dropdown",(e=>{if(e.relatedTarget.matches('[role="combobox"]')){const combobox=e.relatedTarget,listbox=document.querySelector("#".concat(combobox.getAttribute("aria-controls"),'[role="listbox"]'));if(listbox){const selectedOption=listbox.querySelector('[role="option"][aria-selected="true"]');setTimeout((()=>{if(selectedOption)selectedOption.classList.add("active"),combobox.setAttribute("aria-activedescendant",selectedOption.id);else{const firstOption=listbox.querySelector('[role="option"]');firstOption.setAttribute("aria-selected","true"),firstOption.classList.add("active"),combobox.setAttribute("aria-activedescendant",firstOption.id)}}),0)}}})),(0,_jquery.default)(document).on("hidden.bs.dropdown",(e=>{if(e.relatedTarget.matches('[role="combobox"]')){const combobox=e.relatedTarget,listbox=document.querySelector("#".concat(combobox.getAttribute("aria-controls"),'[role="listbox"]'));combobox.removeAttribute("aria-activedescendant"),listbox&&setTimeout((()=>{listbox.querySelectorAll('.active[role="option"]').forEach((option=>{option.classList.remove("active")}))}),0)}})),document.addEventListener("keydown",(e=>{if(e.target.matches('[role="combobox"][aria-controls]:not([aria-haspopup=dialog])')){const combobox=e.target,trigger=e.key;let next=null;const listbox=document.querySelector("#".concat(combobox.getAttribute("aria-controls"),'[role="listbox"]')),options=listbox.querySelectorAll('[role="option"]'),activeOption=listbox.querySelector('.active[role="option"]'),editable=combobox.hasAttribute("aria-autocomplete");if(options&&(activeOption||editable)){if("ArrowDown"==trigger){for(let i=0;i{const option=e.target.closest('[role="listbox"] [role="option"]');if(option){const listbox=option.closest('[role="listbox"]'),combobox=document.querySelector('[role="combobox"][aria-controls="'.concat(listbox.id,'"]'));combobox&&(combobox.focus(),selectOption(combobox,option))}})),document.addEventListener("change",(e=>{if(e.target.matches('input[type="hidden"][id]')){const combobox=document.querySelector('[role="combobox"][data-input-element="'.concat(e.target.id,'"]')),option=e.target.parentElement.querySelector('[role="option"][data-value="'.concat(e.target.value,'"]'));combobox&&option&&selectOption(combobox,option)}}));const selectOption=(combobox,option)=>{const oldSelectedOption=option.closest('[role="listbox"]').querySelector('[role="option"][aria-selected="true"]');if(oldSelectedOption!=option&&(oldSelectedOption&&oldSelectedOption.removeAttribute("aria-selected"),option.setAttribute("aria-selected","true")),combobox.hasAttribute("value")?combobox.value=option.textContent.replace(/[\n\r]+|[\s]{2,}/g," ").trim():combobox.textContent=option.textContent,combobox.dataset.inputElement){const inputElement=document.getElementById(combobox.dataset.inputElement);inputElement&&inputElement.value!=option.dataset.value&&(inputElement.value=option.dataset.value,inputElement.dispatchEvent(new Event("change",{bubbles:!0})))}}})(),window.addEventListener("load",(()=>{const alerts=document.querySelectorAll('[data-aria-autofocus="true"][role="alert"]');Array.prototype.forEach.call(alerts,(autofocusElement=>{autofocusElement.innerHTML+=" ",autofocusElement.removeAttribute("data-aria-autofocus")}))})),tabElementFix(),document.addEventListener("keydown",(e=>{e.target.matches('[data-toggle="collapse"]')&&" "===e.key&&(e.preventDefault(),e.target.click())}))}}));
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_pending=_interopRequireDefault(_pending),FocusLockManager=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(FocusLockManager);const dropdownFix=()=>{let focusEnd=!1;const setFocusEnd=function(){let end=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];focusEnd=end},shiftFocus=function(element){let focusCheck=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;const pendingPromise=new _pending.default("core/aria:delayed-focus");setTimeout((()=>{focusCheck&&!focusCheck()||element.focus(),pendingPromise.resolve()}),50)},handleMenuButton=e=>{const trigger=e.key;let fixFocus=!1;if(" "!==trigger&&"Enter"!==trigger||(fixFocus=!0,e.preventDefault(),e.target.click()),"ArrowUp"!==trigger&&"ArrowDown"!==trigger||(fixFocus=!0),!fixFocus)return;const menu=e.target.parentElement.querySelector('[role="menu"]');let menuItems=!1,foundMenuItem=!1,textInput=!1;menu&&(menuItems=menu.querySelectorAll('[role="menuitem"]'),textInput=e.target.parentElement.querySelector('[data-action="search"]')),menuItems&&menuItems.length>0&&("ArrowUp"===trigger?setFocusEnd():setFocusEnd(!1),foundMenuItem=(()=>{const result=focusEnd;return focusEnd=!1,result})()?menuItems[menuItems.length-1]:menuItems[0]),textInput&&shiftFocus(textInput),foundMenuItem&&null===textInput&&shiftFocus(foundMenuItem)};document.addEventListener("keypress",(e=>{if(e.target.matches('.dropdown [role="menu"] [role="menuitem"]')){const menu=e.target.closest('[role="menu"]');if(!menu)return;const menuItems=menu.querySelectorAll('[role="menuitem"]');if(!menuItems)return;const trigger=e.key.toLowerCase();for(let i=0;i{if(e.target.matches('[data-toggle="dropdown"]')&&handleMenuButton(e),e.target.matches('.dropdown [role="menu"] [role="menuitem"]')){const trigger=e.key;let next=!1;const menu=e.target.closest('[role="menu"]');if(!menu)return;const menuItems=menu.querySelectorAll('[role="menuitem"]');if(!menuItems)return;if("ArrowDown"==trigger){for(let i=0;i{const dialog=e.target.querySelector("#".concat(e.relatedTarget.getAttribute("aria-controls"),'[role="dialog"]'));dialog&&setTimeout((()=>{FocusLockManager.trapFocus(dialog)}))})),(0,_jquery.default)(".dropdown").on("hidden.bs.dropdown",(e=>{e.target.querySelector("#".concat(e.relatedTarget.getAttribute("aria-controls"),'[role="dialog"]'))&&FocusLockManager.untrapFocus();const trigger=e.target.querySelector('[data-toggle="dropdown"]'),focused=document.activeElement!=document.body?document.activeElement:null;trigger&&focused&&e.target.contains(focused)&&shiftFocus(trigger,(()=>document.activeElement===document.body||e.target.contains(document.activeElement)))}))},tabElementFix=()=>{document.addEventListener("keydown",(e=>{["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Home","End"].includes(e.key)&&e.target.matches('[role="tablist"] [role="tab"]')&&(e=>{const tabList=e.target.closest('[role="tablist"]'),vertical="vertical"==tabList.getAttribute("aria-orientation"),rtl=window.right_to_left(),arrowNext=vertical?"ArrowDown":rtl?"ArrowLeft":"ArrowRight",arrowPrevious=vertical?"ArrowUp":rtl?"ArrowRight":"ArrowLeft",tabs=Array.prototype.filter.call(tabList.querySelectorAll('[role="tab"]'),(tab=>!!tab.offsetHeight));for(let i=0;i{if(e.target.matches('[role="tablist"] [data-toggle="tab"], [role="tablist"] [data-toggle="pill"]')){const tabs=e.target.closest('[role="tablist"]').querySelectorAll('[data-toggle="tab"], [data-toggle="pill"]');e.preventDefault(),(0,_jquery.default)(e.target).tab("show"),tabs.forEach((tab=>{tab.tabIndex=-1})),e.target.tabIndex=0}}))};_exports.init=()=>{dropdownFix(),(()=>{(0,_jquery.default)(document).on("show.bs.dropdown",(e=>{if(e.relatedTarget.matches('[role="combobox"]')){const combobox=e.relatedTarget,listbox=document.querySelector("#".concat(combobox.getAttribute("aria-controls"),'[role="listbox"]'));if(listbox){const selectedOption=listbox.querySelector('[role="option"][aria-selected="true"]');setTimeout((()=>{if(selectedOption)selectedOption.classList.add("active"),combobox.setAttribute("aria-activedescendant",selectedOption.id);else{const firstOption=listbox.querySelector('[role="option"]');firstOption.setAttribute("aria-selected","true"),firstOption.classList.add("active"),combobox.setAttribute("aria-activedescendant",firstOption.id)}}),0)}}})),(0,_jquery.default)(document).on("hidden.bs.dropdown",(e=>{if(e.relatedTarget.matches('[role="combobox"]')){const combobox=e.relatedTarget,listbox=document.querySelector("#".concat(combobox.getAttribute("aria-controls"),'[role="listbox"]'));combobox.removeAttribute("aria-activedescendant"),listbox&&setTimeout((()=>{listbox.querySelectorAll('.active[role="option"]').forEach((option=>{option.classList.remove("active")}))}),0)}})),document.addEventListener("keydown",(e=>{if(e.target.matches('[role="combobox"][aria-controls]:not([aria-haspopup=dialog])')){const combobox=e.target,trigger=e.key;let next=null;const listbox=document.querySelector("#".concat(combobox.getAttribute("aria-controls"),'[role="listbox"]')),options=listbox.querySelectorAll('[role="option"]'),activeOption=listbox.querySelector('.active[role="option"]'),editable=combobox.hasAttribute("aria-autocomplete");if(options&&(activeOption||editable)){if("ArrowDown"==trigger){for(let i=0;i{const option=e.target.closest('[role="listbox"] [role="option"]');if(option){const listbox=option.closest('[role="listbox"]'),combobox=document.querySelector('[role="combobox"][aria-controls="'.concat(listbox.id,'"]'));combobox&&(combobox.focus(),selectOption(combobox,option))}})),document.addEventListener("change",(e=>{if(e.target.matches('input[type="hidden"][id]')){const combobox=document.querySelector('[role="combobox"][data-input-element="'.concat(e.target.id,'"]')),option=e.target.parentElement.querySelector('[role="option"][data-value="'.concat(e.target.value,'"]'));combobox&&option&&selectOption(combobox,option)}}));const selectOption=(combobox,option)=>{const oldSelectedOption=option.closest('[role="listbox"]').querySelector('[role="option"][aria-selected="true"]');if(oldSelectedOption!=option&&(oldSelectedOption&&oldSelectedOption.removeAttribute("aria-selected"),option.setAttribute("aria-selected","true")),combobox.hasAttribute("value")?combobox.value=option.textContent.replace(/[\n\r]+|[\s]{2,}/g," ").trim():combobox.textContent=option.textContent,combobox.dataset.inputElement){const inputElement=document.getElementById(combobox.dataset.inputElement);inputElement&&inputElement.value!=option.dataset.value&&(inputElement.value=option.dataset.value,inputElement.dispatchEvent(new Event("change",{bubbles:!0})))}}})(),window.addEventListener("load",(()=>{const alerts=document.querySelectorAll('[data-aria-autofocus="true"][role="alert"]');Array.prototype.forEach.call(alerts,(autofocusElement=>{autofocusElement.innerHTML+=" ",autofocusElement.removeAttribute("data-aria-autofocus")}))})),tabElementFix(),document.addEventListener("keydown",(e=>{e.target.matches('[data-toggle="collapse"]')&&" "===e.key&&(e.preventDefault(),e.target.click())}))}}));
//# sourceMappingURL=aria.min.js.map
\ No newline at end of file
diff --git a/theme/boost/amd/build/aria.min.js.map b/theme/boost/amd/build/aria.min.js.map
index 397c1eaff7e..c5641ebf9f8 100644
--- a/theme/boost/amd/build/aria.min.js.map
+++ b/theme/boost/amd/build/aria.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"aria.min.js","sources":["../src/aria.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Enhancements to Bootstrap components for accessibility.\n *\n * @module theme_boost/aria\n * @copyright 2018 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Pending from 'core/pending';\n\n/**\n * Drop downs from bootstrap don't support keyboard accessibility by default.\n */\nconst dropdownFix = () => {\n let focusEnd = false;\n const setFocusEnd = (end = true) => {\n focusEnd = end;\n };\n const getFocusEnd = () => {\n const result = focusEnd;\n focusEnd = false;\n return result;\n };\n\n // Special handling for navigation keys when menu is open.\n const shiftFocus = (element, focusCheck = null) => {\n const pendingPromise = new Pending('core/aria:delayed-focus');\n setTimeout(() => {\n if (!focusCheck || focusCheck()) {\n element.focus();\n }\n\n pendingPromise.resolve();\n }, 50);\n };\n\n // Event handling for the dropdown menu button.\n const handleMenuButton = e => {\n const trigger = e.key;\n let fixFocus = false;\n\n // Space key or Enter key opens the menu.\n if (trigger === ' ' || trigger === 'Enter') {\n fixFocus = true;\n // Cancel random scroll.\n e.preventDefault();\n // Open the menu instead.\n e.target.click();\n }\n\n // Up and Down keys also open the menu.\n if (trigger === 'ArrowUp' || trigger === 'ArrowDown') {\n fixFocus = true;\n }\n\n if (!fixFocus) {\n // No need to fix the focus. Return early.\n return;\n }\n\n // Fix the focus on the menu items when the menu is opened.\n const menu = e.target.parentElement.querySelector('[role=\"menu\"]');\n let menuItems = false;\n let foundMenuItem = false;\n let textInput = false;\n\n if (menu) {\n menuItems = menu.querySelectorAll('[role=\"menuitem\"]');\n textInput = e.target.parentElement.querySelector('[data-action=\"search\"]');\n }\n\n if (menuItems && menuItems.length > 0) {\n // Up key opens the menu at the end.\n if (trigger === 'ArrowUp') {\n setFocusEnd();\n } else {\n setFocusEnd(false);\n }\n\n if (getFocusEnd()) {\n foundMenuItem = menuItems[menuItems.length - 1];\n } else {\n // The first menu entry, pretty reasonable.\n foundMenuItem = menuItems[0];\n }\n }\n\n if (textInput) {\n shiftFocus(textInput);\n }\n if (foundMenuItem && textInput === null) {\n shiftFocus(foundMenuItem);\n }\n };\n\n // Search for menu items by finding the first item that has\n // text starting with the typed character (case insensitive).\n document.addEventListener('keypress', e => {\n if (e.target.matches('.dropdown [role=\"menu\"] [role=\"menuitem\"]')) {\n const menu = e.target.closest('[role=\"menu\"]');\n if (!menu) {\n return;\n }\n const menuItems = menu.querySelectorAll('[role=\"menuitem\"]');\n if (!menuItems) {\n return;\n }\n\n const trigger = e.key.toLowerCase();\n\n for (let i = 0; i < menuItems.length; i++) {\n const item = menuItems[i];\n const itemText = item.text.trim().toLowerCase();\n if (itemText.indexOf(trigger) == 0) {\n shiftFocus(item);\n break;\n }\n }\n }\n });\n\n // Keyboard navigation for arrow keys, home and end keys.\n document.addEventListener('keydown', e => {\n\n // We only want to set focus when users access the dropdown via keyboard as per\n // guidelines defined in w3 aria practices 1.1 menu-button.\n if (e.target.matches('[data-toggle=\"dropdown\"]')) {\n handleMenuButton(e);\n }\n\n if (e.target.matches('.dropdown [role=\"menu\"] [role=\"menuitem\"]')) {\n const trigger = e.key;\n let next = false;\n const menu = e.target.closest('[role=\"menu\"]');\n\n if (!menu) {\n return;\n }\n const menuItems = menu.querySelectorAll('[role=\"menuitem\"]');\n if (!menuItems) {\n return;\n }\n // Down key.\n if (trigger == 'ArrowDown') {\n for (let i = 0; i < menuItems.length - 1; i++) {\n if (menuItems[i] == e.target) {\n next = menuItems[i + 1];\n break;\n }\n }\n if (!next) {\n // Wrap to first item.\n next = menuItems[0];\n }\n } else if (trigger == 'ArrowUp') {\n // Up key.\n for (let i = 1; i < menuItems.length; i++) {\n if (menuItems[i] == e.target) {\n next = menuItems[i - 1];\n break;\n }\n }\n if (!next) {\n // Wrap to last item.\n next = menuItems[menuItems.length - 1];\n }\n } else if (trigger == 'Home') {\n // Home key.\n next = menuItems[0];\n\n } else if (trigger == 'End') {\n // End key.\n next = menuItems[menuItems.length - 1];\n }\n\n // Variable next is set if we do want to act on the keypress.\n if (next) {\n e.preventDefault();\n shiftFocus(next);\n }\n return;\n }\n });\n\n $('.dropdown').on('hidden.bs.dropdown', e => {\n // We need to focus on the menu trigger.\n const trigger = e.target.querySelector('[data-toggle=\"dropdown\"]');\n const focused = document.activeElement != document.body ? document.activeElement : null;\n if (trigger && focused && e.target.contains(focused)) {\n shiftFocus(trigger, () => {\n if (document.activeElement === document.body) {\n // If the focus is currently on the body, then we can safely assume that the focus needs to be updated.\n return true;\n }\n\n // If the focus is on a child of the clicked element still, then update the focus.\n return e.target.contains(document.activeElement);\n });\n }\n });\n};\n\n/**\n * A lot of Bootstrap's out of the box features don't work if dropdown items are not focusable.\n */\nconst comboboxFix = () => {\n $(document).on('show.bs.dropdown', e => {\n if (e.relatedTarget.matches('[role=\"combobox\"]')) {\n const combobox = e.relatedTarget;\n const listbox = document.querySelector(`#${combobox.getAttribute('aria-controls')}[role=\"listbox\"]`);\n\n if (listbox) {\n const selectedOption = listbox.querySelector('[role=\"option\"][aria-selected=\"true\"]');\n\n // To make sure ArrowDown doesn't move the active option afterwards.\n setTimeout(() => {\n if (selectedOption) {\n selectedOption.classList.add('active');\n combobox.setAttribute('aria-activedescendant', selectedOption.id);\n } else {\n const firstOption = listbox.querySelector('[role=\"option\"]');\n firstOption.setAttribute('aria-selected', 'true');\n firstOption.classList.add('active');\n combobox.setAttribute('aria-activedescendant', firstOption.id);\n }\n }, 0);\n }\n }\n });\n\n $(document).on('hidden.bs.dropdown', e => {\n if (e.relatedTarget.matches('[role=\"combobox\"]')) {\n const combobox = e.relatedTarget;\n const listbox = document.querySelector(`#${combobox.getAttribute('aria-controls')}[role=\"listbox\"]`);\n\n combobox.removeAttribute('aria-activedescendant');\n\n if (listbox) {\n setTimeout(() => {\n // Undo all previously highlighted options.\n listbox.querySelectorAll('.active[role=\"option\"]').forEach(option => {\n option.classList.remove('active');\n });\n }, 0);\n }\n }\n });\n\n // Handling keyboard events for both navigating through and selecting options.\n document.addEventListener('keydown', e => {\n if (e.target.matches('[role=\"combobox\"][aria-controls]:not([aria-haspopup=dialog])')) {\n const combobox = e.target;\n const trigger = e.key;\n let next = null;\n const listbox = document.querySelector(`#${combobox.getAttribute('aria-controls')}[role=\"listbox\"]`);\n const options = listbox.querySelectorAll('[role=\"option\"]');\n const activeOption = listbox.querySelector('.active[role=\"option\"]');\n const editable = combobox.hasAttribute('aria-autocomplete');\n\n // Under the special case that the dropdown menu is being shown as a result of the key press (like when the user\n // presses ArrowDown or Enter or ... to open the dropdown menu), activeOption is not set yet.\n // It's because of a race condition with show.bs.dropdown event handler.\n if (options && (activeOption || editable)) {\n if (trigger == 'ArrowDown') {\n for (let i = 0; i < options.length - 1; i++) {\n if (options[i] == activeOption) {\n next = options[i + 1];\n break;\n }\n }\n if (editable && !next) {\n next = options[0];\n }\n } if (trigger == 'ArrowUp') {\n for (let i = 1; i < options.length; i++) {\n if (options[i] == activeOption) {\n next = options[i - 1];\n break;\n }\n }\n if (editable && !next) {\n next = options[options.length - 1];\n }\n } else if (trigger == 'Home') {\n next = options[0];\n } else if (trigger == 'End') {\n next = options[options.length - 1];\n } else if ((trigger == ' ' && !editable) || trigger == 'Enter') {\n e.preventDefault();\n selectOption(combobox, activeOption);\n } else if (!editable) {\n // Search for options by finding the first option that has\n // text starting with the typed character (case insensitive).\n for (let i = 0; i < options.length; i++) {\n const option = options[i];\n const optionText = option.textContent.trim().toLowerCase();\n const keyPressed = e.key.toLowerCase();\n if (optionText.indexOf(keyPressed) == 0) {\n next = option;\n break;\n }\n }\n }\n\n // Variable next is set if we do want to act on the keypress.\n if (next) {\n e.preventDefault();\n if (activeOption) {\n activeOption.classList.remove('active');\n }\n next.classList.add('active');\n combobox.setAttribute('aria-activedescendant', next.id);\n next.scrollIntoView({block: 'nearest'});\n }\n }\n }\n });\n\n document.addEventListener('click', e => {\n const option = e.target.closest('[role=\"listbox\"] [role=\"option\"]');\n if (option) {\n const listbox = option.closest('[role=\"listbox\"]');\n const combobox = document.querySelector(`[role=\"combobox\"][aria-controls=\"${listbox.id}\"]`);\n if (combobox) {\n combobox.focus();\n selectOption(combobox, option);\n }\n }\n });\n\n // In case some code somewhere else changes the value of the combobox.\n document.addEventListener('change', e => {\n if (e.target.matches('input[type=\"hidden\"][id]')) {\n const combobox = document.querySelector(`[role=\"combobox\"][data-input-element=\"${e.target.id}\"]`);\n const option = e.target.parentElement.querySelector(`[role=\"option\"][data-value=\"${e.target.value}\"]`);\n\n if (combobox && option) {\n selectOption(combobox, option);\n }\n }\n });\n\n const selectOption = (combobox, option) => {\n const listbox = option.closest('[role=\"listbox\"]');\n const oldSelectedOption = listbox.querySelector('[role=\"option\"][aria-selected=\"true\"]');\n\n if (oldSelectedOption != option) {\n if (oldSelectedOption) {\n oldSelectedOption.removeAttribute('aria-selected');\n }\n option.setAttribute('aria-selected', 'true');\n }\n\n if (combobox.hasAttribute('value')) {\n combobox.value = option.textContent.replace(/[\\n\\r]+|[\\s]{2,}/g, ' ').trim();\n } else {\n combobox.textContent = option.textContent;\n }\n\n if (combobox.dataset.inputElement) {\n const inputElement = document.getElementById(combobox.dataset.inputElement);\n if (inputElement && (inputElement.value != option.dataset.value)) {\n inputElement.value = option.dataset.value;\n inputElement.dispatchEvent(new Event('change', {bubbles: true}));\n }\n }\n };\n};\n\n/**\n * After page load, focus on any element with special autofocus attribute.\n */\nconst autoFocus = () => {\n window.addEventListener(\"load\", () => {\n const alerts = document.querySelectorAll('[data-aria-autofocus=\"true\"][role=\"alert\"]');\n Array.prototype.forEach.call(alerts, autofocusElement => {\n // According to the specification an role=\"alert\" region is only read out on change to the content\n // of that region.\n autofocusElement.innerHTML += ' ';\n autofocusElement.removeAttribute('data-aria-autofocus');\n });\n });\n};\n\n/**\n * Changes the focus to the correct tab based on the key that is pressed.\n * @param {KeyboardEvent} e\n */\nconst updateTabFocus = e => {\n const tabList = e.target.closest('[role=\"tablist\"]');\n const vertical = tabList.getAttribute('aria-orientation') == 'vertical';\n const rtl = window.right_to_left();\n const arrowNext = vertical ? 'ArrowDown' : (rtl ? 'ArrowLeft' : 'ArrowRight');\n const arrowPrevious = vertical ? 'ArrowUp' : (rtl ? 'ArrowRight' : 'ArrowLeft');\n const tabs = Array.prototype.filter.call(\n tabList.querySelectorAll('[role=\"tab\"]'),\n tab => !!tab.offsetHeight); // We only work with the visible tabs.\n\n for (let i = 0; i < tabs.length; i++) {\n tabs[i].index = i;\n }\n\n switch (e.key) {\n case arrowNext:\n e.preventDefault();\n if (e.target.index !== undefined && tabs[e.target.index + 1]) {\n tabs[e.target.index + 1].focus();\n } else {\n tabs[0].focus();\n }\n break;\n case arrowPrevious:\n e.preventDefault();\n if (e.target.index !== undefined && tabs[e.target.index - 1]) {\n tabs[e.target.index - 1].focus();\n } else {\n tabs[tabs.length - 1].focus();\n }\n break;\n case 'Home':\n e.preventDefault();\n tabs[0].focus();\n break;\n case 'End':\n e.preventDefault();\n tabs[tabs.length - 1].focus();\n }\n};\n\n/**\n * Fix accessibility issues regarding tab elements focus and their tab order in Bootstrap navs.\n */\nconst tabElementFix = () => {\n document.addEventListener('keydown', e => {\n if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(e.key)) {\n if (e.target.matches('[role=\"tablist\"] [role=\"tab\"]')) {\n updateTabFocus(e);\n }\n }\n });\n\n document.addEventListener('click', e => {\n if (e.target.matches('[role=\"tablist\"] [data-toggle=\"tab\"], [role=\"tablist\"] [data-toggle=\"pill\"]')) {\n const tabs = e.target.closest('[role=\"tablist\"]').querySelectorAll('[data-toggle=\"tab\"], [data-toggle=\"pill\"]');\n e.preventDefault();\n $(e.target).tab('show');\n tabs.forEach(tab => {\n tab.tabIndex = -1;\n });\n e.target.tabIndex = 0;\n }\n });\n};\n\n/**\n * Fix keyboard interaction with Bootstrap Collapse elements.\n *\n * @see {@link https://www.w3.org/TR/wai-aria-practices-1.1/#disclosure|WAI-ARIA Authoring Practices 1.1 - Disclosure (Show/Hide)}\n */\nconst collapseFix = () => {\n document.addEventListener('keydown', e => {\n if (e.target.matches('[data-toggle=\"collapse\"]')) {\n // Pressing space should toggle expand/collapse.\n if (e.key === ' ') {\n e.preventDefault();\n e.target.click();\n }\n }\n });\n};\n\nexport const init = () => {\n dropdownFix();\n comboboxFix();\n autoFocus();\n tabElementFix();\n collapseFix();\n};\n"],"names":["dropdownFix","focusEnd","setFocusEnd","end","shiftFocus","element","focusCheck","pendingPromise","Pending","setTimeout","focus","resolve","handleMenuButton","e","trigger","key","fixFocus","preventDefault","target","click","menu","parentElement","querySelector","menuItems","foundMenuItem","textInput","querySelectorAll","length","result","getFocusEnd","document","addEventListener","matches","closest","toLowerCase","i","item","text","trim","indexOf","next","on","focused","activeElement","body","contains","tabElementFix","includes","tabList","vertical","getAttribute","rtl","window","right_to_left","arrowNext","arrowPrevious","tabs","Array","prototype","filter","call","tab","offsetHeight","index","undefined","updateTabFocus","forEach","tabIndex","relatedTarget","combobox","listbox","selectedOption","classList","add","setAttribute","id","firstOption","removeAttribute","option","remove","options","activeOption","editable","hasAttribute","selectOption","optionText","textContent","keyPressed","scrollIntoView","block","value","oldSelectedOption","replace","dataset","inputElement","getElementById","dispatchEvent","Event","bubbles","comboboxFix","alerts","autofocusElement","innerHTML"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"aria.min.js","sources":["../src/aria.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Enhancements to Bootstrap components for accessibility.\n *\n * @module theme_boost/aria\n * @copyright 2018 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Pending from 'core/pending';\nimport * as FocusLockManager from 'core/local/aria/focuslock';\n\n/**\n * Drop downs from bootstrap don't support keyboard accessibility by default.\n */\nconst dropdownFix = () => {\n let focusEnd = false;\n const setFocusEnd = (end = true) => {\n focusEnd = end;\n };\n const getFocusEnd = () => {\n const result = focusEnd;\n focusEnd = false;\n return result;\n };\n\n // Special handling for navigation keys when menu is open.\n const shiftFocus = (element, focusCheck = null) => {\n const pendingPromise = new Pending('core/aria:delayed-focus');\n setTimeout(() => {\n if (!focusCheck || focusCheck()) {\n element.focus();\n }\n\n pendingPromise.resolve();\n }, 50);\n };\n\n // Event handling for the dropdown menu button.\n const handleMenuButton = e => {\n const trigger = e.key;\n let fixFocus = false;\n\n // Space key or Enter key opens the menu.\n if (trigger === ' ' || trigger === 'Enter') {\n fixFocus = true;\n // Cancel random scroll.\n e.preventDefault();\n // Open the menu instead.\n e.target.click();\n }\n\n // Up and Down keys also open the menu.\n if (trigger === 'ArrowUp' || trigger === 'ArrowDown') {\n fixFocus = true;\n }\n\n if (!fixFocus) {\n // No need to fix the focus. Return early.\n return;\n }\n\n // Fix the focus on the menu items when the menu is opened.\n const menu = e.target.parentElement.querySelector('[role=\"menu\"]');\n let menuItems = false;\n let foundMenuItem = false;\n let textInput = false;\n\n if (menu) {\n menuItems = menu.querySelectorAll('[role=\"menuitem\"]');\n textInput = e.target.parentElement.querySelector('[data-action=\"search\"]');\n }\n\n if (menuItems && menuItems.length > 0) {\n // Up key opens the menu at the end.\n if (trigger === 'ArrowUp') {\n setFocusEnd();\n } else {\n setFocusEnd(false);\n }\n\n if (getFocusEnd()) {\n foundMenuItem = menuItems[menuItems.length - 1];\n } else {\n // The first menu entry, pretty reasonable.\n foundMenuItem = menuItems[0];\n }\n }\n\n if (textInput) {\n shiftFocus(textInput);\n }\n if (foundMenuItem && textInput === null) {\n shiftFocus(foundMenuItem);\n }\n };\n\n // Search for menu items by finding the first item that has\n // text starting with the typed character (case insensitive).\n document.addEventListener('keypress', e => {\n if (e.target.matches('.dropdown [role=\"menu\"] [role=\"menuitem\"]')) {\n const menu = e.target.closest('[role=\"menu\"]');\n if (!menu) {\n return;\n }\n const menuItems = menu.querySelectorAll('[role=\"menuitem\"]');\n if (!menuItems) {\n return;\n }\n\n const trigger = e.key.toLowerCase();\n\n for (let i = 0; i < menuItems.length; i++) {\n const item = menuItems[i];\n const itemText = item.text.trim().toLowerCase();\n if (itemText.indexOf(trigger) == 0) {\n shiftFocus(item);\n break;\n }\n }\n }\n });\n\n // Keyboard navigation for arrow keys, home and end keys.\n document.addEventListener('keydown', e => {\n\n // We only want to set focus when users access the dropdown via keyboard as per\n // guidelines defined in w3 aria practices 1.1 menu-button.\n if (e.target.matches('[data-toggle=\"dropdown\"]')) {\n handleMenuButton(e);\n }\n\n if (e.target.matches('.dropdown [role=\"menu\"] [role=\"menuitem\"]')) {\n const trigger = e.key;\n let next = false;\n const menu = e.target.closest('[role=\"menu\"]');\n\n if (!menu) {\n return;\n }\n const menuItems = menu.querySelectorAll('[role=\"menuitem\"]');\n if (!menuItems) {\n return;\n }\n // Down key.\n if (trigger == 'ArrowDown') {\n for (let i = 0; i < menuItems.length - 1; i++) {\n if (menuItems[i] == e.target) {\n next = menuItems[i + 1];\n break;\n }\n }\n if (!next) {\n // Wrap to first item.\n next = menuItems[0];\n }\n } else if (trigger == 'ArrowUp') {\n // Up key.\n for (let i = 1; i < menuItems.length; i++) {\n if (menuItems[i] == e.target) {\n next = menuItems[i - 1];\n break;\n }\n }\n if (!next) {\n // Wrap to last item.\n next = menuItems[menuItems.length - 1];\n }\n } else if (trigger == 'Home') {\n // Home key.\n next = menuItems[0];\n\n } else if (trigger == 'End') {\n // End key.\n next = menuItems[menuItems.length - 1];\n }\n\n // Variable next is set if we do want to act on the keypress.\n if (next) {\n e.preventDefault();\n shiftFocus(next);\n }\n return;\n }\n });\n\n $('.dropdown').on('shown.bs.dropdown', e => {\n const dialog = e.target.querySelector(`#${e.relatedTarget.getAttribute('aria-controls')}[role=\"dialog\"]`);\n if (dialog) {\n // Use setTimeout to make sure the dialog is positioned correctly to prevent random scrolling.\n setTimeout(() => {\n FocusLockManager.trapFocus(dialog);\n });\n }\n });\n\n $('.dropdown').on('hidden.bs.dropdown', e => {\n const dialog = e.target.querySelector(`#${e.relatedTarget.getAttribute('aria-controls')}[role=\"dialog\"]`);\n if (dialog) {\n FocusLockManager.untrapFocus();\n }\n\n // We need to focus on the menu trigger.\n const trigger = e.target.querySelector('[data-toggle=\"dropdown\"]');\n const focused = document.activeElement != document.body ? document.activeElement : null;\n if (trigger && focused && e.target.contains(focused)) {\n shiftFocus(trigger, () => {\n if (document.activeElement === document.body) {\n // If the focus is currently on the body, then we can safely assume that the focus needs to be updated.\n return true;\n }\n\n // If the focus is on a child of the clicked element still, then update the focus.\n return e.target.contains(document.activeElement);\n });\n }\n });\n};\n\n/**\n * A lot of Bootstrap's out of the box features don't work if dropdown items are not focusable.\n */\nconst comboboxFix = () => {\n $(document).on('show.bs.dropdown', e => {\n if (e.relatedTarget.matches('[role=\"combobox\"]')) {\n const combobox = e.relatedTarget;\n const listbox = document.querySelector(`#${combobox.getAttribute('aria-controls')}[role=\"listbox\"]`);\n\n if (listbox) {\n const selectedOption = listbox.querySelector('[role=\"option\"][aria-selected=\"true\"]');\n\n // To make sure ArrowDown doesn't move the active option afterwards.\n setTimeout(() => {\n if (selectedOption) {\n selectedOption.classList.add('active');\n combobox.setAttribute('aria-activedescendant', selectedOption.id);\n } else {\n const firstOption = listbox.querySelector('[role=\"option\"]');\n firstOption.setAttribute('aria-selected', 'true');\n firstOption.classList.add('active');\n combobox.setAttribute('aria-activedescendant', firstOption.id);\n }\n }, 0);\n }\n }\n });\n\n $(document).on('hidden.bs.dropdown', e => {\n if (e.relatedTarget.matches('[role=\"combobox\"]')) {\n const combobox = e.relatedTarget;\n const listbox = document.querySelector(`#${combobox.getAttribute('aria-controls')}[role=\"listbox\"]`);\n\n combobox.removeAttribute('aria-activedescendant');\n\n if (listbox) {\n setTimeout(() => {\n // Undo all previously highlighted options.\n listbox.querySelectorAll('.active[role=\"option\"]').forEach(option => {\n option.classList.remove('active');\n });\n }, 0);\n }\n }\n });\n\n // Handling keyboard events for both navigating through and selecting options.\n document.addEventListener('keydown', e => {\n if (e.target.matches('[role=\"combobox\"][aria-controls]:not([aria-haspopup=dialog])')) {\n const combobox = e.target;\n const trigger = e.key;\n let next = null;\n const listbox = document.querySelector(`#${combobox.getAttribute('aria-controls')}[role=\"listbox\"]`);\n const options = listbox.querySelectorAll('[role=\"option\"]');\n const activeOption = listbox.querySelector('.active[role=\"option\"]');\n const editable = combobox.hasAttribute('aria-autocomplete');\n\n // Under the special case that the dropdown menu is being shown as a result of the key press (like when the user\n // presses ArrowDown or Enter or ... to open the dropdown menu), activeOption is not set yet.\n // It's because of a race condition with show.bs.dropdown event handler.\n if (options && (activeOption || editable)) {\n if (trigger == 'ArrowDown') {\n for (let i = 0; i < options.length - 1; i++) {\n if (options[i] == activeOption) {\n next = options[i + 1];\n break;\n }\n }\n if (editable && !next) {\n next = options[0];\n }\n } if (trigger == 'ArrowUp') {\n for (let i = 1; i < options.length; i++) {\n if (options[i] == activeOption) {\n next = options[i - 1];\n break;\n }\n }\n if (editable && !next) {\n next = options[options.length - 1];\n }\n } else if (trigger == 'Home') {\n next = options[0];\n } else if (trigger == 'End') {\n next = options[options.length - 1];\n } else if ((trigger == ' ' && !editable) || trigger == 'Enter') {\n e.preventDefault();\n selectOption(combobox, activeOption);\n } else if (!editable) {\n // Search for options by finding the first option that has\n // text starting with the typed character (case insensitive).\n for (let i = 0; i < options.length; i++) {\n const option = options[i];\n const optionText = option.textContent.trim().toLowerCase();\n const keyPressed = e.key.toLowerCase();\n if (optionText.indexOf(keyPressed) == 0) {\n next = option;\n break;\n }\n }\n }\n\n // Variable next is set if we do want to act on the keypress.\n if (next) {\n e.preventDefault();\n if (activeOption) {\n activeOption.classList.remove('active');\n }\n next.classList.add('active');\n combobox.setAttribute('aria-activedescendant', next.id);\n next.scrollIntoView({block: 'nearest'});\n }\n }\n }\n });\n\n document.addEventListener('click', e => {\n const option = e.target.closest('[role=\"listbox\"] [role=\"option\"]');\n if (option) {\n const listbox = option.closest('[role=\"listbox\"]');\n const combobox = document.querySelector(`[role=\"combobox\"][aria-controls=\"${listbox.id}\"]`);\n if (combobox) {\n combobox.focus();\n selectOption(combobox, option);\n }\n }\n });\n\n // In case some code somewhere else changes the value of the combobox.\n document.addEventListener('change', e => {\n if (e.target.matches('input[type=\"hidden\"][id]')) {\n const combobox = document.querySelector(`[role=\"combobox\"][data-input-element=\"${e.target.id}\"]`);\n const option = e.target.parentElement.querySelector(`[role=\"option\"][data-value=\"${e.target.value}\"]`);\n\n if (combobox && option) {\n selectOption(combobox, option);\n }\n }\n });\n\n const selectOption = (combobox, option) => {\n const listbox = option.closest('[role=\"listbox\"]');\n const oldSelectedOption = listbox.querySelector('[role=\"option\"][aria-selected=\"true\"]');\n\n if (oldSelectedOption != option) {\n if (oldSelectedOption) {\n oldSelectedOption.removeAttribute('aria-selected');\n }\n option.setAttribute('aria-selected', 'true');\n }\n\n if (combobox.hasAttribute('value')) {\n combobox.value = option.textContent.replace(/[\\n\\r]+|[\\s]{2,}/g, ' ').trim();\n } else {\n combobox.textContent = option.textContent;\n }\n\n if (combobox.dataset.inputElement) {\n const inputElement = document.getElementById(combobox.dataset.inputElement);\n if (inputElement && (inputElement.value != option.dataset.value)) {\n inputElement.value = option.dataset.value;\n inputElement.dispatchEvent(new Event('change', {bubbles: true}));\n }\n }\n };\n};\n\n/**\n * After page load, focus on any element with special autofocus attribute.\n */\nconst autoFocus = () => {\n window.addEventListener(\"load\", () => {\n const alerts = document.querySelectorAll('[data-aria-autofocus=\"true\"][role=\"alert\"]');\n Array.prototype.forEach.call(alerts, autofocusElement => {\n // According to the specification an role=\"alert\" region is only read out on change to the content\n // of that region.\n autofocusElement.innerHTML += ' ';\n autofocusElement.removeAttribute('data-aria-autofocus');\n });\n });\n};\n\n/**\n * Changes the focus to the correct tab based on the key that is pressed.\n * @param {KeyboardEvent} e\n */\nconst updateTabFocus = e => {\n const tabList = e.target.closest('[role=\"tablist\"]');\n const vertical = tabList.getAttribute('aria-orientation') == 'vertical';\n const rtl = window.right_to_left();\n const arrowNext = vertical ? 'ArrowDown' : (rtl ? 'ArrowLeft' : 'ArrowRight');\n const arrowPrevious = vertical ? 'ArrowUp' : (rtl ? 'ArrowRight' : 'ArrowLeft');\n const tabs = Array.prototype.filter.call(\n tabList.querySelectorAll('[role=\"tab\"]'),\n tab => !!tab.offsetHeight); // We only work with the visible tabs.\n\n for (let i = 0; i < tabs.length; i++) {\n tabs[i].index = i;\n }\n\n switch (e.key) {\n case arrowNext:\n e.preventDefault();\n if (e.target.index !== undefined && tabs[e.target.index + 1]) {\n tabs[e.target.index + 1].focus();\n } else {\n tabs[0].focus();\n }\n break;\n case arrowPrevious:\n e.preventDefault();\n if (e.target.index !== undefined && tabs[e.target.index - 1]) {\n tabs[e.target.index - 1].focus();\n } else {\n tabs[tabs.length - 1].focus();\n }\n break;\n case 'Home':\n e.preventDefault();\n tabs[0].focus();\n break;\n case 'End':\n e.preventDefault();\n tabs[tabs.length - 1].focus();\n }\n};\n\n/**\n * Fix accessibility issues regarding tab elements focus and their tab order in Bootstrap navs.\n */\nconst tabElementFix = () => {\n document.addEventListener('keydown', e => {\n if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(e.key)) {\n if (e.target.matches('[role=\"tablist\"] [role=\"tab\"]')) {\n updateTabFocus(e);\n }\n }\n });\n\n document.addEventListener('click', e => {\n if (e.target.matches('[role=\"tablist\"] [data-toggle=\"tab\"], [role=\"tablist\"] [data-toggle=\"pill\"]')) {\n const tabs = e.target.closest('[role=\"tablist\"]').querySelectorAll('[data-toggle=\"tab\"], [data-toggle=\"pill\"]');\n e.preventDefault();\n $(e.target).tab('show');\n tabs.forEach(tab => {\n tab.tabIndex = -1;\n });\n e.target.tabIndex = 0;\n }\n });\n};\n\n/**\n * Fix keyboard interaction with Bootstrap Collapse elements.\n *\n * @see {@link https://www.w3.org/TR/wai-aria-practices-1.1/#disclosure|WAI-ARIA Authoring Practices 1.1 - Disclosure (Show/Hide)}\n */\nconst collapseFix = () => {\n document.addEventListener('keydown', e => {\n if (e.target.matches('[data-toggle=\"collapse\"]')) {\n // Pressing space should toggle expand/collapse.\n if (e.key === ' ') {\n e.preventDefault();\n e.target.click();\n }\n }\n });\n};\n\nexport const init = () => {\n dropdownFix();\n comboboxFix();\n autoFocus();\n tabElementFix();\n collapseFix();\n};\n"],"names":["dropdownFix","focusEnd","setFocusEnd","end","shiftFocus","element","focusCheck","pendingPromise","Pending","setTimeout","focus","resolve","handleMenuButton","e","trigger","key","fixFocus","preventDefault","target","click","menu","parentElement","querySelector","menuItems","foundMenuItem","textInput","querySelectorAll","length","result","getFocusEnd","document","addEventListener","matches","closest","toLowerCase","i","item","text","trim","indexOf","next","on","dialog","relatedTarget","getAttribute","FocusLockManager","trapFocus","untrapFocus","focused","activeElement","body","contains","tabElementFix","includes","tabList","vertical","rtl","window","right_to_left","arrowNext","arrowPrevious","tabs","Array","prototype","filter","call","tab","offsetHeight","index","undefined","updateTabFocus","forEach","tabIndex","combobox","listbox","selectedOption","classList","add","setAttribute","id","firstOption","removeAttribute","option","remove","options","activeOption","editable","hasAttribute","selectOption","optionText","textContent","keyPressed","scrollIntoView","block","value","oldSelectedOption","replace","dataset","inputElement","getElementById","dispatchEvent","Event","bubbles","comboboxFix","alerts","autofocusElement","innerHTML"],"mappings":"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"}
\ No newline at end of file
diff --git a/theme/boost/amd/src/aria.js b/theme/boost/amd/src/aria.js
index 6793b0fb44a..6c40ba3b8f6 100644
--- a/theme/boost/amd/src/aria.js
+++ b/theme/boost/amd/src/aria.js
@@ -23,6 +23,7 @@
import $ from 'jquery';
import Pending from 'core/pending';
+import * as FocusLockManager from 'core/local/aria/focuslock';
/**
* Drop downs from bootstrap don't support keyboard accessibility by default.
@@ -198,7 +199,22 @@ const dropdownFix = () => {
}
});
+ $('.dropdown').on('shown.bs.dropdown', e => {
+ const dialog = e.target.querySelector(`#${e.relatedTarget.getAttribute('aria-controls')}[role="dialog"]`);
+ if (dialog) {
+ // Use setTimeout to make sure the dialog is positioned correctly to prevent random scrolling.
+ setTimeout(() => {
+ FocusLockManager.trapFocus(dialog);
+ });
+ }
+ });
+
$('.dropdown').on('hidden.bs.dropdown', e => {
+ const dialog = e.target.querySelector(`#${e.relatedTarget.getAttribute('aria-controls')}[role="dialog"]`);
+ if (dialog) {
+ FocusLockManager.untrapFocus();
+ }
+
// We need to focus on the menu trigger.
const trigger = e.target.querySelector('[data-toggle="dropdown"]');
const focused = document.activeElement != document.body ? document.activeElement : null;