1// ************************************** 2// Ministry A11Y navigation 3// ************************************** 4 5var a11yNav = jQuery('.a11y-navigation'); 6 7if (a11yNav != undefined) { 8 var a11yNavUl = jQuery(".a11y-nav"); 9 var a11yToggle = jQuery(".js-toggle-special-nav") 10 let a11yFocusTarget = "li"; 11 if (a11yNav.data("focusTarget")) a11yFocusTarget = a11yNav.data("focusTarget"); 12 13 a11yToggle.each(function(i) { 14 var button = jQuery(this); 15 var a11ySubNav = button.parent().children(".a11y-nav__sub"); 16 17 // Calculate dropdown top value 18 var topMargin = (a11yNavUl.outerHeight() + 1) + "px"; 19 20 // Case of Intermin 21 if (jQuery('body').hasClass('sm')) { 22 var topMargin = a11yNavUl.outerHeight() + "px"; 23 } 24 25 // if opened by default 26 if (button.attr('aria-expanded') === 'true') { 27 a11ySubNav.css('top',topMargin); 28 a11ySubNav.removeClass('d-none'); 29 a11yNav.css('height', a11ySubNav.outerHeight() + a11yNavUl.outerHeight()); 30 button.parent().addClass('special-nav-open') 31 32 jQuery( window ).resize(function() { 33 a11ySubNav.css('top', topMargin); 34 a11yNav.css('height', a11ySubNav.outerHeight() + a11yNavUl.outerHeight()); 35 }) 36 } 37 38 // Toggle dropdown visibility 39 button.on("click", function() { 40 41 jQuery('.js-toggle-special-nav').each(function(idx,elem) { 42 if (jQuery(elem) !== button) { 43 jQuery(elem).find('.icon').removeClass('icon-minus').addClass('icon-plus'); 44 } 45 }); 46 47 jQuery('.special-nav').each(function() { 48 jQuery(this).addClass('d-none') 49 }); 50 51 var ariaExpanded = jQuery(this).attr('aria-expanded'); 52 var icon = jQuery(this).find('span[role]'); 53 54 // dropdown is already open 55 if ( ariaExpanded === 'true') { 56 57 // Close dropown 58 a11ySubNav.addClass('d-none'); 59 a11ySubNav.attr('aria-hidden', 'true'); 60 a11yNav.removeAttr('style'); 61 jQuery(this).attr('aria-expanded','false'); 62 icon.removeClass('icon-minus').addClass('icon-plus'); 63 button.parent().removeClass('special-nav-open'); 64 button.find('.a11y-nav__toggle_text').text('Ãppna\x20undermenyn'); 65 66 a11yNavUl.children('li').each(function(){ 67 if (jQuery(this).hasClass('current')) { 68 69 var dropdown = jQuery(this).children('.simple-dropdown'); 70 71 if (dropdown) { 72 dropdown.removeClass('d-none'); 73 a11yNav.css('height', dropdown.outerHeight() + a11yNavUl.outerHeight()); 74 75 } 76 } 77 }); 78 79 if (document.activeElement.closest('ul').classList?.contains('a11y-navgroup')) button.focus(); 80 81 } else { 82 // Remove all 'special-nav-open' classes 83 button.parents('.a11y-nav').find('.special-nav-open').each(function () { 84 jQuery(this).removeClass('special-nav-open') 85 }); 86 87 // Open dropdown 88 a11ySubNav.attr('aria-hidden', 'false') 89 a11ySubNav.removeClass('d-none'); 90 a11yNav.css('height', a11ySubNav.outerHeight() + a11yNavUl.outerHeight()); 91 jQuery(this).attr('aria-expanded','true'); 92 icon.removeClass('icon-plus').addClass('icon-minus'); 93 button.parent().addClass('special-nav-open'); 94 95 // After opening sub menu move focus to element 96 setTimeout(function(){ 97 98 if (a11yFocusTarget === 'li') a11ySubNav.find('li:first > a').focus(); 99 if (a11yFocusTarget === 'ul') { 100 a11ySubNav.find('.a11y-navgroup').first().focus(); 101 } 102 },100); 103 104 setTimeout(function(){ 105 button.find('.a11y-nav__toggle_text').text('Stäng\x20undermenyn') 106 },500); 107 108 109 } 110 111 112 // Close open dropdown on ESC 113 114 document.addEventListener('keyup', function(e) { 115 if (e.key !== 'Escape') return; 116 117 // Close dropown 118 a11ySubNav.addClass('d-none'); 119 a11ySubNav.attr('aria-hidden', 'true') 120 a11yNav.removeAttr('style'); 121 button.attr('aria-expanded','false') 122 icon.removeClass('icon-minus').addClass('icon-plus') 123 button.parent().removeClass('special-nav-open') 124 button.find('.a11y-nav__toggle_text').text('Ãppna\x20undermenyn') 125 126 a11yNavUl.children('li').each(function(){ 127 if (jQuery(this).hasClass('current')) { 128 const dropdown = jQuery(this).children('.simple-dropdown') 129 if (dropdown !== undefined) { 130 dropdown.removeClass('d-none'); 131 a11yNav.css('height', dropdown.outerHeight() + a11yNavUl.outerHeight()); 132 } 133 } 134 }); 135 }, false); 136 137 // Close by outside click 138 document.addEventListener('click', function(event) { 139 140 event.stopPropagation(); 141 142 if (event.target.closest('.site-theme__navigation')) return; 143 if (a11yNav.parent('header').length === 0) return; 144 145 // Close dropown 146 a11ySubNav.addClass('d-none'); 147 a11ySubNav.attr('aria-hidden', 'true') 148 a11yNav.removeAttr('style'); 149 button.attr('aria-expanded', 'false') 150 icon.removeClass('icon-minus').addClass('icon-plus') 151 button.parent().removeClass('special-nav-open') 152 button.find('.a11y-nav__toggle_text').text('Ãppna\x20undermenyn') 153 154 a11yNavUl.children('li').each(function () { 155 if (jQuery(this).hasClass('current')) { 156 const dropdown = jQuery(this).children('.simple-dropdown') 157 if (dropdown) { 158 dropdown.removeClass('d-none'); 159 a11yNav.css('height', dropdown.outerHeight() + a11yNavUl.outerHeight()); 160 } 161 } 162 }); 163 },false); 164 165 }); 166 }); 167 168 // in case other dropowns 169 jQuery('.simple-dropdown').each(function() { 170 var dropdown = jQuery(this); 171 dropdown.removeClass('d-none'); 172 dropdown.css('top', (a11yNavUl.outerHeight() + 1) + "px"); 173 a11yNav.css('height', dropdown.outerHeight() + a11yNavUl.outerHeight()); 174 175 jQuery( window ).resize(function() { 176 dropdown.css('top', (a11yNavUl.outerHeight() + 1) + "px"); 177 a11yNav.css('height', dropdown.outerHeight() + a11yNavUl.outerHeight()); 178 }) 179 180 }); 181 182} 183// --------------------------- 184// A11Y keyboard navigation 185// --------------------------- 186 187var navigation = document.querySelectorAll('.a11y-navigation')[0]; 188if (navigation != undefined) { 189 190 var menu = navigation.querySelectorAll('.a11y-nav')[0] 191 if (menu != undefined) { 192 menu.addEventListener('keydown',function(event) { 193 EVENT_KEY = event.key; 194 switch (EVENT_KEY) { 195 case 'ArrowLeft': 196 moveLeft() 197 break; 198 case 'Left': 199 moveLeft() 200 break; 201 case 'Right': 202 moveRight() 203 break; 204 case 'ArrowRight': 205 moveRight() 206 break; 207 case 'ArrowDown': 208 event.preventDefault(); 209 moveDown(); 210 break; 211 case 'Down': 212 event.preventDefault(); 213 moveDown(); 214 break; 215 case 'ArrowUp': 216 event.preventDefault(); 217 moveUp() 218 break; 219 case 'Up': 220 event.preventDefault(); 221 moveUp() 222 break; 223 } 224 225 226 },false) 227 } 228} 229 230 231 232 233/// --------------------------------- 234/// A11Y KEYBOARD NAVIGATION 235/// --------------------------------- 236 237function moveLeft() { 238 var target = document.activeElement 239 var parent = target.parentElement; 240 var parentUL = parent.parentElement; 241 var id = parentUL.id 242 var focusable = parentUL.querySelectorAll('#'+id+' > li > a[href], #'+id+' > li > button') 243 var firstFocusable = focusable[0]
244 var lastFocusbale = focusable[focusable.length - 1] 245 246 var focusIndex = [].indexOf.call(focusable, document.activeElement); 247 248 if (parentUL.id === 'a11y-nav-root') { 249 if (target != firstFocusable) { 250 focusable[focusIndex - 1].focus(); 251 } else { 252 focusable[focusable.length - 1].focus() 253 } 254 } else { 255 // If focus is inside child menu jump to previous main level element 256 if (target != firstFocusable) { 257 focusable[focusIndex - 1].focus(); 258 } else { 259 var grandParent = parentUL.parentElement.parentElement; 260 var grandParentUl = grandParent.parentElement; 261 var parentFocusable = grandParentUl.querySelectorAll('#' + grandParentUl.id + ' > li > a[href], #' + grandParentUl.id + ' > li > button') 262 var parentButton = grandParent.querySelectorAll('button')[0] 263 if (parentButton === undefined) { 264 parentButton = grandParent.querySelectorAll('a')[0] 265 } 266 var parentFocusIndex = [].indexOf.call(parentFocusable, parentButton); 267 268 if (parentFocusIndex > 1) { 269 parentFocusable[parentFocusIndex - 2].focus() 270 } else { 271 parentFocusable[parentFocusable.length - 1].focus() 272 } 273 } 274 } 275} 276 277function moveRight() { 278 var target = document.activeElement 279 var parent = target.parentElement; 280 var parentUL = parent.parentElement; 281 var id = parentUL.id 282 var focusable = parentUL.querySelectorAll('#'+id+' > li > a[href], #'+id+' > li > button') 283 var firstFocusable = focusable[0] 284 var lastFocusbale = focusable[focusable.length - 1] 285 286 var focusIndex = [].indexOf.call(focusable, target); 287 if (parentUL.id === 'a11y-nav-root') { 288 if (target != lastFocusbale) { 289 focusable[focusIndex + 1].focus(); 290 } else { 291 focusable[0].focus(); 292 } 293 } else { 294 if (target != lastFocusbale) { 295 focusable[focusIndex + 1].focus(); 296 } else { 297 var grandParent = parentUL.parentElement.parentElement; 298 var grandParentUl = grandParent.parentElement; 299 var parentFocusable = grandParentUl.querySelectorAll('#'+grandParentUl.id+' > li > a[href], #'+grandParentUl.id+' > li > button') 300 var parentButton = grandParent.querySelectorAll('button')[0] 301 if (parentButton === undefined) { 302 parentButton = grandParent.querySelectorAll('a')[0] 303 } 304 var parentFocusIndex = [].indexOf.call(parentFocusable, parentButton); 305 306 if (parentFocusIndex < parentFocusable.length) { 307 parentFocusable[parentFocusIndex + 1].focus() 308 } else { 309 parentFocusable[0].focus() 310 } 311 } 312 } 313} 314 315function moveUp() { 316 var target = document.activeElement 317 var parent = target.parentElement; 318 var parentUL = parent.parentElement; 319 var id = parentUL.id; 320 // Check that we are inside in sub-menu 321 if (parentUL.classList.contains('a11y-navgroup')) { 322 var focusable = parentUL.querySelectorAll('#'+id+' > li > a[href]') 323 var firstFocusable = focusable[0] 324 var focusIndex = [].indexOf.call(focusable, target); 325 326 if (target != firstFocusable) { 327 focusable[focusIndex - 1].focus(); 328 } else { 329 var grandParent = parentUL.parentElement.parentElement; 330 var button = grandParent.querySelectorAll('button')[0] 331 if (button != undefined) { 332 button.focus(); 333 } else { 334 grandParent.querySelectorAll('a')[0].focus() 335 } 336 } 337 } 338} 339 340function moveDown() { 341 var target = document.activeElement 342 var parent = target.parentElement; 343 var parentUL = parent.parentElement; 344 var id = parentUL.id; 345 // Check if element has children && clicked on first level element 346 347 if (parent.classList.contains('a11y-nav__item--has-children')) { 348 var elem = document.activeElement; 349 var subNav = elem.parentElement.querySelectorAll('ul')[0] 350 var button = elem.parentElement.querySelectorAll('button')[0] 351 if (button != undefined) { 352 button.setAttribute('aria-expanded','true') 353 } 354 355 parent.classList.add('dropdown--expanded') 356 subNav.setAttribute('aria-hidden','false') 357 358 setTimeout(function() { 359 var firstElement = subNav.querySelectorAll('a')[0] 360 firstElement.focus(); 361 }, 500) 362 363 } else { 364 var focusable = parentUL.querySelectorAll('#'+id+' > li > a[href], #'+id+' > li > button') 365 var firstFocusable = focusable[0]
366 var lastFocusbale = focusable[focusable.length - 1] 367 368 var focusIndex = [].indexOf.call(focusable, document.activeElement); 369 370 if (document.activeElement != lastFocusbale) { 371 focusable[focusIndex + 1].focus(); 372 } else { 373 firstFocusable.focus() 374 } 375 } 376 377} 378 379function closeDropdown(elem, focus) { 380 focus = (typeof focus !== 'undefined') ? focus : true 381 var parentUL = elem.parentElement.parentElement; 382 var grandParent = parentUL.parentElement; 383 var button = grandParent.querySelectorAll('button')[0] 384 if (focus) { 385 button.focus(); 386 } 387 button.setAttribute('aria-expanded','false') 388 grandParent.classList.remove('dropdown--expanded') 389 parentUL.setAttribute('aria-hidden','true') 390} 391 392
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.