{"version":3,"file":"aria.min.js","sources":["https:\/\/dl1.cuni.cz\/theme\/boost\/amd\/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\n if (menu) {\n menuItems = menu.querySelectorAll('[role=\"menuitem\"]');\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 (foundMenuItem) {\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 \/\/ If it's a click event, then no element is focused because the clicked element is inside a closed dropdown.\n const focused = e.clickEvent?.target || (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' && !editable) {\n next = options[0];\n } else if (trigger == 'End' && !editable) {\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 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.dataset.shortText || option.textContent.replace(\/[\\n\\r]+|[\\s]{2,}\/g, ' ').trim();\n } else {\n combobox.textContent = option.dataset.shortText || 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","querySelectorAll","length","result","getFocusEnd","document","addEventListener","matches","closest","toLowerCase","i","item","text","trim","indexOf","next","on","dialog","relatedTarget","getAttribute","FocusLockManager","trapFocus","untrapFocus","focused","clickEvent","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","dataset","shortText","replace","inputElement","getElementById","dispatchEvent","Event","bubbles","comboboxFix","alerts","autofocusElement","innerHTML"],"mappings":"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"}