PageSourceSearch

https://migri.fi/o/common-ui-resources/standalone/a11y/js/a11y-nav…=chrome&languageId=sv_SE&t=1790607354000

js migri.fi collected 2026-10-02 02:58:01 UTC 14,327 bytes, 392 lines download raw bytes

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.