1/** 2 * @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org> 3 * @license GNU General Public License version 2 or later; see LICENSE.txt 4 */ 5 6(() => { 7 8 function topLevelMouseOver(el, settings) { 9 const ulChild = el.querySelector('ul'); 10 if (ulChild) { 11 ulChild.setAttribute('aria-hidden', 'false'); 12 ulChild.classList.add(settings.menuHoverClass); 13 } 14 } 15 function topLevelMouseOut(el, settings) { 16 const ulChild = el.querySelector('ul'); 17 if (ulChild) { 18 ulChild.setAttribute('aria-hidden', 'true'); 19 ulChild.classList.remove(settings.menuHoverClass); 20 } 21 } 22 function setupNavigation(nav) { 23 const settings = { 24 menuHoverClass: 'show-menu'}; 25 26 // Set tabIndex to -1 so that top_level_childs can't receive focus until menu is open 27 nav.querySelectorAll(':scope > li').forEach(topLevelEl => { 28 const linkEl = topLevelEl.querySelector('a'); 29 if (linkEl) { 30 linkEl.tabIndex = '0'; 31 linkEl.addEventListener('mouseover', topLevelMouseOver(topLevelEl, settings)); 32 linkEl.addEventListener('mouseout', topLevelMouseOut(topLevelEl, settings)); 33 } 34 const spanEl = topLevelEl.querySelector('span'); 35 if (spanEl) { 36 if (spanEl.parentNode.nodeName !== 'A') { 37 spanEl.tabIndex = '0'; 38 } 39 spanEl.addEventListener('mouseover', topLevelMouseOver(topLevelEl, settings)); 40 spanEl.addEventListener('mouseout', topLevelMouseOut(topLevelEl, settings)); 41 } 42 topLevelEl.addEventListener('mouseover', ({ 43 currentTarget 44 }) => { 45 const ulChild = currentTarget.querySelector('ul'); 46 if (ulChild) { 47 ulChild.setAttribute('aria-hidden', 'false'); 48 ulChild.classList.add(settings.menuHoverClass); 49 } 50 }); 51 topLevelEl.addEventListener('mouseout', ({ 52 currentTarget 53 }) => { 54 const ulChild = currentTarget.querySelector('ul'); 55 if (ulChild) { 56 ulChild.setAttribute('aria-hidden', 'true'); 57 ulChild.classList.remove(settings.menuHoverClass); 58 } 59 }); 60 topLevelEl.addEventListener('focus', ({ 61 currentTarget 62 }) => { 63 const ulChild = currentTarget.querySelector('ul'); 64 if (ulChild) { 65 ulChild.setAttribute('aria-hidden', 'true'); 66 ulChild.classList.add(settings.menuHoverClass); 67 } 68 }); 69 topLevelEl.addEventListener('blur', ({ 70 currentTarget 71 }) => { 72 const ulChild = currentTarget.querySelector('ul'); 73 if (ulChild) { 74 ulChild.setAttribute('aria-hidden', 'false'); 75 ulChild.classList.remove(settings.menuHoverClass); 76 } 77 }); 78 topLevelEl.addEventListener('keydown', event => { 79 const keyName = event.key; 80 const curEl = event.target; 81 const curLiEl = curEl.parentElement; 82 const curUlEl = curLiEl.parentElement; 83 let prevLiEl = curLiEl.previousElementSibling; 84 let nextLiEl = curLiEl.nextElementSibling; 85 if (!prevLiEl) { 86 prevLiEl = curUlEl.children[curUlEl.children.length - 1]; 87 } 88 if (!nextLiEl) { 89 [nextLiEl] = curUlEl.children; 90 } 91 switch (keyName) { 92 case 'ArrowLeft': 93 event.preventDefault(); 94 { 95 prevLiEl.children[0].focus(); 96 } 97 break; 98 case 'ArrowRight': 99 event.preventDefault(); 100 { 101 nextLiEl.children[0].focus(); 102 } 103 break; 104 case 'ArrowUp': 105 { 106 event.preventDefault(); 107 const parent = curLiEl.parentElement.parentElement; 108 if (parent.nodeName === 'LI') { 109 parent.children[0].focus(); 110 } else { 111 prevLiEl.children[0].focus(); 112 } 113 break; 114 } 115 case 'ArrowDown': 116 event.preventDefault(); 117 if (curLiEl.classList.contains('parent')) { 118 const child = curLiEl.querySelector('ul'); 119 if (child != null) { 120 const childLi = child.querySelector('li'); 121 childLi.children[0].focus(); 122 } else { 123 nextLiEl.children[0].focus(); 124 } 125 } else { 126 nextLiEl.children[0].focus(); 127 } 128 break; 129 } 130 }); 131 }); 132 } 133 document.addEventListener('DOMContentLoaded', () => { 134 document.querySelectorAll('.nav').forEach(nav => setupNavigation(nav)); 135 }); 136})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.