PageSourceSearch

https://ladakh.gov.in/wp-content/themes/sdo-theme/js/menu.js

js ladakh.gov.in collected 2026-10-02 10:55:16 UTC 34,703 bytes, 942 lines download raw bytes

1// Code for Acessible Main menu
2
3jQuery(document).ready(function($) {
4//adding outline on menu if meniitems focused
5    $('.menuWrapper nav')
6    .on('focusin', function () {
7        $(this).addClass('menu-focused');
8    })
9    .on('focusout', function () {
10        let $this = $(this);
11        setTimeout(function () {
12        if (!$this.find(':focus').length) {
13            $this.removeClass('menu-focused');
14        }
15        }, 10);
16    });
17
18
19     $('.menuWrapper nav ul ul.sub-menu').each(function () {
20        const $submenu = $(this);
21        const $parentLi = $submenu.closest('li'); // parent <li> with sub-menu
22        const $parentLink = $parentLi.children('a').first();
23
24        if ($parentLink.length) {
25            const linkText = $.trim($parentLink.clone().children().remove().end().text());
26            if (linkText !== '') {
27                $submenu.attr('aria-label', linkText + ' submenu');
28            }
29        }
30    });
31
32 function updateAriaExpanded($li, expanded) {
33        const $link = $li.children("a");
34        if ($li.children("ul.sub-menu").length) {
35            $link.attr("aria-expanded", expanded ? "true" : "false");
36        } else {
37            $link.removeAttr("aria-expanded");
38        }
39    }
40
41    function openMenu() {
42        if ($("body").hasClass("rtl")) {
43            $("#overflowMenu").animate({ left: "0px" });
44        } else {
45            $("#overflowMenu").animate({ right: "0px" });
46        }
47        $('#overflowMenu ul').find(' > li > a').attr('tabindex', 0);
48        $('#overflowMenu a.closeMenu').attr('tabindex', 0);
49    }
50
51    
52    function applyAriaRoles() {
53        const $mainMenu = $(".menuWrapper nav > ul");
54
55        $mainMenu.attr({ "role": "menubar"});
56
57        const $topLevelLinks = $mainMenu.find("> li > a");
58
59        $topLevelLinks.each(function(index) {
60            const $link = $(this);
61            $link.attr("role", "menuitem");
62            $link.attr("tabindex", index === 0 ? "0" : "-1");
63
64            const $parentLi = $link.closest("li");
65            $parentLi.attr("role", "none");
66
67            if ($parentLi.children("ul.sub-menu").length) {
68                $link.attr("aria-haspopup", "true");
69                updateAriaExpanded($parentLi, false);
70            } else {
71                $link.removeAttr("aria-haspopup aria-expanded");
72            }
73        });
74
75        $(".menuWrapper nav ul ul.sub-menu").attr("role", "menu");
76        $(".menuWrapper nav ul ul.sub-menu > li").attr("role", "none");
77        $(".menuWrapper nav ul ul.sub-menu > li > a").attr("role", "menuitem").attr("tabindex", "-1"); // set all submenu items to -1 initially
78    }
79
80    applyAriaRoles();
81
82
83
84    function closeSubMenu($li) {
85        $li.find("> ul.sub-menu").slideUp().attr("aria-hidden", "true");
86        updateAriaExpanded($li, false);
87        $li.find("> ul.sub-menu > li > a").attr("tabIndex", -1);
88        $li.find("> ul.sub-menu > li > ul.sub-menu").slideUp().attr("aria-hidden", "true");
89        $li.find("> ul.sub-menu > li > a").each(function() {
90            updateAriaExpanded($(this).parent(), false);
91        });
92    }
93
94    function openSubMenu($li, focusLast = false, focusFirst = false) {
95        $li.find("> ul.sub-menu").slideDown().attr("aria-hidden", "false");
96        updateAriaExpanded($li, true);
97        $li.find("> ul.sub-menu > li > a").attr("tabIndex", 0);
98        if ($li.closest("ul.sub-menu").length > 0) {
99            $li.find("> ul.sub-menu").css({ display: "block", right: "-250px" });
100        }
101        if (focusLast) {
102            $li.find("> ul.sub-menu > li:last > a").focus();
103        } else if (focusFirst) {
104            $li.find("> ul.sub-menu > li:first > a").focus();
105        }
106    }
107
108    function onMenuItemClick(event) {
109        const $submenu = $(this).children("ul.sub-menu");
110        const $link = $(this).children("a");
111        if ($submenu.length) {
112            $(this).siblings("li").find("ul.sub-menu").slideUp().attr("aria-hidden", "true")
113                .siblings("a").each(function() {
114                    updateAriaExpanded($(this).parent(), false);
115                });
116
117            const isVisible = $submenu.is(":visible");
118            // $submenu.slideToggle();
119            $submenu.attr("aria-hidden", isVisible ? "true" : "false");
120            updateAriaExpanded($(this), !isVisible);
121            $submenu.find("> li > a").attr("tabIndex", isVisible ? -1 : 0);
122            if ($(this).hasClass("has-sub-child")) {
123                $submenu.css('left', '100%');
124            }
125            event.stopPropagation();
126        }
127    }
128
129    $(".menuWrapper nav ul li").each(function () {
130        if ($(this).children("ul.sub-menu").length) {
131            $(this).on("click", onMenuItemClick);
132        }
133    });
134
135
136    //Keyboard Navigation Handler for Main Menu, Overflow Menu and Submenus
137
138    $(document).on("keydown", function(event) {
139        const $currentElement = $(document.activeElement);
140
141        const $menuWrapper = $(".menuWrapper nav, .moreNav");
142        if ($menuWrapper.has($currentElement).length === 0) {
143            return;
144        }
145
146        const isMainMenuItem =
147            $currentElement.closest(".menuWrapper nav > ul > li").length > 0 ||
148            $currentElement.closest(".moreNav").length > 0;
149
150        const isInSubmenu = $currentElement.closest("ul.sub-menu").length > 0;
151
152        const $mainMenuItems = $(".menuWrapper nav > ul > li > a:visible, .moreNav > a:visible").filter(function() {
153            return $(this).closest("li").parents("ul").length === 1;
154        });
155
156        const currentIndex = $mainMenuItems.get().indexOf($currentElement[0]);
157
158        const $parentLi = $currentElement.closest("li");
159        const $submenuItems = isInSubmenu ? $currentElement.closest("ul.sub-menu").find("> li > a") : [];
160        const submenuIndex = isInSubmenu ? $submenuItems.index($currentElement) : -1;
161
162        // ENTER / SPACE
163        if (event.which === 13 || event.which === 32) {
164            event.preventDefault();
165            if ($parentLi.children("ul.sub-menu").length) {
166                openSubMenu($parentLi, false, true);
167                // $parentLi.children("a").attr("aria-expanded", "true");
168            } else {
169                window.location.href = $currentElement.attr("href");
170                // $parentLi.children("a").attr("aria-expanded", "false");
171            }
172        }
173
174
175        // LEFT / RIGHT / UP / DOWN / HOME / END / ALPHABETICAL KEYS
176        else if ([37, 38, 39, 40, 36, 35].includes(event.which) || (event.key.length === 1 && /[a-zA-Z0-9]/.test(event.key))) {
177            event.preventDefault();
178
179        if (event.which === 37) { // LEFT
180            if (!isInSubmenu && isMainMenuItem) {
181                    const prevIndex = currentIndex > 0 ? currentIndex - 1 : $mainMenuItems.length - 1;
182                    $mainMenuItems.eq(prevIndex).focus();
183                } else if (isInSubmenu) {
184                    const $parentMenuItem = $currentElement.closest("ul.sub-menu").parent("li");
185                    closeSubMenu($parentMenuItem);
186                    $parentMenuItem.find("> a").focus().attr("aria-expanded", "false");
187                }
188            } 
189
190
191                else if (event.which === 39) { // RIGHT
192                    let $currentLi = $currentElement.closest("li");
193
194                    // Case 1: On a submenu item that has its own nested submenu
195                    if (isInSubmenu) {
196                        let $nestedSubmenu = $currentLi.children("ul.sub-menu");
197                        if ($nestedSubmenu.length > 0) {
198                            // Open nested submenu
199                            $nestedSubmenu.attr("aria-hidden", "false").slideDown().css({ display: "block", right: "-250px" });
200                            $currentLi.children("a").attr("aria-expanded", "true");
201                           
202                            // Focus first item in nested submenu
203                            $nestedSubmenu.find('a[role="menuitem"]:visible').first().focus();
204                        } else {
205                            // If no nested submenu, jump to next top-level menu item
206                            let $topParentLi = $currentLi;
207                            while ($topParentLi.closest("ul.sub-menu").length) {
208                                $topParentLi = $topParentLi.closest("ul.sub-menu").parent("li");
209                            }
210
211                            // Close all open submenus of this top-level item
212                            $topParentLi.find("ul.sub-menu").slideUp().attr("aria-hidden", "true");
213                            $topParentLi.find("a[aria-expanded='true']").attr("aria-expanded", "false");
214                            
215                            const parentIndex = $mainMenuItems.index($topParentLi.find("> a"));
216                            const nextIndex = parentIndex < $mainMenuItems.length - 1 ? parentIndex + 1 : 0;
217                            $mainMenuItems.eq(nextIndex).focus();
218                        }
219                    } 
220
221                    // Case 2: On a main menu item (not in submenu)
222                    else if (!isInSubmenu && isMainMenuItem) {
223                        const nextIndex = currentIndex < $mainMenuItems.length - 1 ? currentIndex + 1 : 0;
224                        $mainMenuItems.eq(nextIndex).focus();
225                    }
226                }
227
228
229
230
231            else if (event.which === 38) { // UP
232               
233                if (isInSubmenu) {
234                    const newIndex = submenuIndex > 0 ? submenuIndex - 1 : $submenuItems.length - 1;
235                    $submenuItems.eq(newIndex).focus();
236                    if ($parentLi.children("ul.sub-menu").length) {
237                        $parentLi.children("a").attr("aria-expanded", "true");
238                    }
239                } else if ($parentLi.children("ul.sub-menu").length) {
240                    openSubMenu($parentLi, true);
241                }
242
243            } 
244   
245            else if (event.which === 40) { // DOWN
246               
247                if (isInSubmenu) {
248                    const newIndex = submenuIndex < $submenuItems.length - 1 ? submenuIndex + 1 : 0;
249                    $submenuItems.eq(newIndex).focus();
250                    if ($parentLi.children("ul.sub-menu").length) {
251                        $parentLi.children("a").attr("aria-expanded", "true");
252                    }
253                } else if ($parentLi.children("ul.sub-menu").length) {
254                    openSubMenu($parentLi, false, true);
255                }
256
257            } 
258
259
260            else if (event.which === 36) { // HOME
261                if (isInSubmenu) {
262                    $submenuItems.eq(0).focus();
263                } else {
264                    $mainMenuItems.eq(0).focus();
265                }
266            } else if (event.which === 35) { // END
267                if (isInSubmenu) {
268                    $submenuItems.eq($submenuItems.length - 1).focus();
269                } else {
270                    $mainMenuItems.eq($mainMenuItems.length - 1).focus();
271                }
272            } 
273            
274            else if (event.key.length === 1 && /[a-zA-Z0-9]/.test(event.key)) { // First-char nav
275                const searchChar = event.key.toLowerCase();
276                const items = isInSubmenu ? $submenuItems : $mainMenuItems;
277                let startIndex = isInSubmenu ? submenuIndex + 1 : currentIndex + 1;
278                if (startIndex >= items.length) startIndex = 0;
279                for (let i = 0; i < items.length; i++) {
280                    const index = (startIndex + i) % items.length;
281                    const itemText = items.eq(index).text().trim().toLowerCase();
282                    if (itemText.startsWith(searchChar)) {
283                        items.eq(index).focus();
284                        break;
285                    }
286                }
287            }
288        }
289
290
291    });
292
293
294    $('html').on('click', function(event) {
295    // If clicked outside both main menu and overflow menu
296    if (!$(event.target).closest('.menuWrapper, #overflowMenu').length) {
297        $(".menuWrapper nav ul li ul.sub-menu").each(function () {
298            $(this)
299                .slideUp()
300                .attr("aria-hidden", "true")
301                .find("> li > a")
302                .attr("tabindex", -1);
303        });
304        $(".menuWrapper nav ul li:has(ul.sub-menu) > a").attr("aria-expanded", "false");
305        $("#overflowMenu .ofMenu ul li ul.sub-menu").each(function () {
306                $(this)
307                    .slideUp()
308                    .attr("aria-hidden", "true")
309                    .find("> li > a")
310                    .attr("tabindex", -1);
311            });
312        $("#overflowMenu .ofMenu ul li:has(ul.sub-menu) > a").attr("aria-expanded", "false");
313        }
314    });
315
316
317    $('.menu').on('click', function(event) {
318        event.stopPropagation();
319    });
320
321
322    $(".menuWrapper nav ul li").each(function () {
323    if ($(this).children("ul.sub-menu").length) {
324        $(this).on("click", onMenuItemClick);
325    }
326});
327
328    $("nav li li").mouseover(function() {
329        if ($(this).children("ul.sub-menu").length == 1) {
330            let parent = $(this);
331            let child_menu = $(this).children("ul.sub-menu");
332            if (
333                $(parent).offset().left + $(parent).width() + $(child_menu).width() >
334                $(window).width()
335            ) {
336                $(child_menu).css("left", "-" + $(parent).width() + "px");
337            } else {
338                $(child_menu).css("right", "-" + $(parent).width() + "px");
339            }
340        }
341    });
342
343    /***** Overflow Navigation Setup *****/
344
345    if ($(window).innerWidth() >= 640) {
346        let menuContanerWidth = $(".menuWrapper .container").width(),
347            itemsTotalWith = 0;
348        $(".menu > ul > li").each(function(s, a) {
349            let itemClone = $(this).clone();
350            itemClone.find('a').attr("tabindex", -1);
351            if (
352                ((itemsTotalWith += $(this).width()),
353                    itemsTotalWith > menuContanerWidth - 100 &&
354                    ($(this).hasClass("moreNav") ||
355                        ($(this).remove(),
356                            $("#overflowMenu .ofMenu > ul").append(itemClone)),
357                        !($(".menu ul .moreNav").length > 0)))
358            ) {
359                let n = $(
360                    '<li class="moreNav" role="none">' +
361                    '<a href="javascript:void(0)" role="menuitem" aria-label="More Menu" title="More Menu"><span class="icon-menu" aria-hidden="true"></span><span class="hide">' +
362                    $(".menuMoreText").html() +
363                    "</span></a></li>"
364                );
365                $(".menuMoreText").html("");
366                $(".menu>ul").append(n);
367                n.click(openMenu);
368            }
369        });
370    }
371
372    // // More Button
373    $(".moreNav a").on("click", function(event) {
374        event.preventDefault(), event.stopPropagation();
375        openMenu();
376    });
377
378
379    $('#overflowMenu').click(function(event) {
380        event.stopPropagation();
381    });
382
383
384    $(".ofMenu ul li").on("click", onMenuItemClick);
385
386    $('.ofMenu ul li').hover(function(e) {
387        $(this).siblings().children('ul.sub-menu').slideUp();
388        $(this).children('ul.sub-menu').slideDown();
389    }, function() {
390        $(this).parent().siblings().children('ul.sub-menu').slideUp();
391    });
392
393    /***** Responsive Navigation Setup *****/
394
395    $(".menuToggle").click(function(event) {
396        event.preventDefault();
397        $(".menuWrapper").stop().slideToggle();
398    });
399
400    if ($(window).width() <= 639) {
401        $(".menu ul li").each(function(index, element) {
402            $(this).off('click');
403            if ($(this).children("ul").length) {
404                $(".indicator").hide();
405                $("<a href='javascript:void(0)' aria-label='Click to expand submenu' class='menu-toggle' role='button'>&nbsp;</a>")
406                    .insertAfter($(element).find(" > a "));
407            }
408        });
409      
410    }
411
412
413    $(function() {
414        $(".menu-toggle").each(function() {
415            var menuTitle = $(this).closest("li").find("> a").text().trim();
416            var expandText = S3WaaSAccessibilityParams.clickToExpand;
417            var submenuWord = S3WaaSAccessibilityParams.submenu;
418
419            $(this)
420            .attr("aria-label", expandText + " " + menuTitle + " " + submenuWord)
421            .attr("aria-expanded", "false");
422        });
423    });
424
425    // On click on menutoggle update aria-labels
426    $(".menu-toggle").click(function(event) {
427        event.preventDefault();
428        $(this).toggleClass("open").parents('li').siblings().children("ul.sub-menu").stop().slideUp('fast');
429        $(this).next("ul.sub-menu").slideToggle('fast');
430
431        $(this).parents('li').siblings().children("a").removeClass("open");
432        $(this).parents('li').siblings().children("a.menu-select").removeClass("menu-select");
433        $(this).prev().toggleClass("menu-select");
434
435        var menuTitle = $(this).closest("li").find("> a").text().trim();
436        var collapseText = S3WaaSAccessibilityParams.clickToCollapse;
437        var expandText   = S3WaaSAccessibilityParams.clickToExpand;
438        var submenuWord  = S3WaaSAccessibilityParams.submenu;
439
440        if ($(this).hasClass("open")) {
441            $(this).attr("aria-label", collapseText + " " + menuTitle + " " + submenuWord).attr("aria-expanded", "true");
442        } else {
443            $(this).attr("aria-label", expandText + " " + menuTitle + " " + submenuWord).attr("aria-expanded", "false");
444        }
445    });
446
447    jQuery(".menuWrapper nav ul li ul.sub-menu > li > a, #overflowMenu .ofMenu ul li ul.submenu > li > a")
448    .on("keydown", function(event) {
449        const $submenu = $(this).closest("ul.sub-menu");
450        const $submenuItems = $submenu.find("> li > a");
451        const currentIndex = $submenuItems.index(this);
452
453        // Trap focus within submenu
454        if (event.which === 9) { // Tab key
455            if (!event.shiftKey && currentIndex === $submenuItems.length - 1) {
456                event.preventDefault();
457                $submenuItems.eq(0).focus();
458            } else if (event.shiftKey && currentIndex === 0) {
459                event.preventDefault();
460                $submenuItems.eq($submenuItems.length - 1).focus();
461            }
462        }
463
464        if (event.which === 27) { // Escape key
465            const $parentLi = $submenu.parent("li");
466            closeSubMenu($parentLi);
467            $parentLi.find("> a").focus().attr('aria-expanded', 'false');
468            event.preventDefault();
469
470        }
471
472    });
473
474    //if no submenu is open and esc key pressed move focus to first focusable element in main
475    jQuery(".menuWrapper nav > ul > li > a").on("keydown", function(event) {
476        if (event.which === 27) {
477            const $levelFirstMenu = jQuery(this).closest("ul.sub-menu");
478
479            if ($levelFirstMenu.length === 0) {
480                const $firstMainLink = jQuery("main a:visible").first();
481                if ($firstMainLink.length) {
482                    $firstMainLink.focus();
483                }
484                event.preventDefault();
485            }
486        }
487    });
488});
489// js to close submenu on ESC key press if submenu is already opened using mouse
490jQuery(function ($) {
491
492    $(document).on('keydown', function (e) {
493        if (e.key === 'Escape') {
494
495            const $nav = $('.menuWrapper nav, #accessibilityMenu').addClass('esc-off');
496            setTimeout(() => $nav.removeClass('esc-off'), 200);
497        }
498    });
499
500});
501
502
503//overflow menu extra js for accessibility
504
505jQuery(document).ready(function($) {
506    const $ov = $('#overflowMenu');
507    const ovWidth = $ov.width();
508
509    // Ensure menu is collapsed on load
510    $('.moreNav > a').attr('aria-expanded', 'false');
511    $ov.hide().css('right', -ovWidth);
512    $ov.find('.sub-menu').hide().attr('aria-hidden', 'true');
513    $ov.find('a').attr('tabindex', -1);
514
515    const $toggleButton = $('.moreNav > a');
516    $toggleButton.attr({
517        'aria-haspopup': 'true',
518        'aria-expanded': 'false',
519        'aria-controls': 'overflowMenu' // connects to the popup menu
520    });
521     $ov.attr({
522            'role': 'dialog',
523            'aria-modal': 'true'
524        });
525
526    function applyAttributes() {
527        $ov.find('.ofMenu > ul').attr('role', 'menu');
528        $ov.find('li').attr('role', 'none');
529        $ov.find('a').attr('role', 'menuitem');
530        $ov.find('li:has(ul.sub-menu) > a')
531            .attr('aria-haspopup', 'true')
532            .attr('aria-expanded', 'false')
533            .attr('tabindex', -1);
534        $ov.find('ul.sub-menu')
535            .attr('role', 'menu')
536            .attr('aria-hidden', 'true')
537            .hide();
538    }
539    applyAttributes();
540
541    function trapWithin($container) {
542        const $focusables = $container.find('a:visible, button:visible').filter('[tabindex!="-1"]');
543        const first = $focusables.first();
544        const last = $focusables.last();
545
546        $focusables.off('keydown.trap').on('keydown.trap', function(e) {
547            const $items = $focusables;
548            const currentIndex = $items.index(this);
549
550            if (e.key === 'Tab') {
551                if (e.shiftKey && this === first[0]) {
552                    e.preventDefault();
553                    last.focus();
554                } else if (!e.shiftKey && this === last[0]) {
555                    e.preventDefault();
556                    first.focus();
557                }
558            }
559
560            if (e.key === 'ArrowDown') {
561                e.preventDefault();
562                const nextIndex = (currentIndex + 1) % $items.length;
563                $items.eq(nextIndex).focus();
564            }
565
566            if (e.key === 'ArrowUp') {
567                e.preventDefault();
568                const prevIndex = (currentIndex - 1 + $items.length) % $items.length;
569                $items.eq(prevIndex).focus();
570            }
571        });
572    }
573
574    function openOverflow() {
575    if ($ov.is(':visible')) return;
576
577    $toggleButton.attr('aria-expanded', 'true');
578
579    $ov.css({
580        right: -ovWidth,
581        display: 'block'
582    }).animate({
583        right: 0
584    }, 400, function () {
585        $ov.find('a').attr('tabindex', 0);
586        // const $firstItem = $ov.find('.ofMenu > ul > li > a:visible').first();
587        // $firstItem.focus();
588        $ov.focus().css('outline','2px solid black')
589        trapWithin($ov);
590
591        announceMenuStatus('More menu expanded');
592    });
593    }
594
595
596    function closeOverflow() {
597    $ov.animate({
598        right: -ovWidth
599    }, 400, function () {
600        $ov.css('display', 'none');
601        $ov.find('a').attr('tabindex', -1);
602        $ov.find('[aria-expanded="true"]').each(function () {
603        $(this)
604            .attr('aria-expanded', 'false')
605            .next('ul.sub-menu')
606            .hide()
607            .attr('aria-hidden', 'true');
608        });
609        $ov.find('*').off('keydown.trap');
610        $toggleButton.attr('aria-expanded', 'false').focus();
611
612        announceMenuStatus('More menu collapsed');
613    });
614    }
615
616    function toggleSubmenu($link, open) {
617        const $sub = $link.next('.sub-menu');
618        $link.attr('aria-expanded', open);
619        $sub.attr('aria-hidden', !open)[open ? 'slideDown' : 'slideUp']();
620        if (open) {
621            const $first = $sub.find('a:visible').first().focus();
622            trapWithin($sub);
623        } else {
624            $sub.find('*').off('keydown.trap');
625            $link.focus();
626        }
627    }
628
629    $('.moreNav > a').on('click keydown', function(e) {
630        if (e.type === 'click' || e.key === 'Enter' || e.key === ' ') {
631            e.preventDefault();
632            openOverflow();
633        }
634    });
635
636    $ov.find('.closeMenu').on('click keydown', function(e) {
637        if (e.type === 'click' || e.key === 'Enter' || e.key === ' ') {
638            e.preventDefault();
639            closeOverflow();
640        }
641    });
642
643    $ov.on('keydown', 'a', function(e) {
644        const key = e.which;
645        const $link = $(this);
646        const $li = $link.parent('li');
647        const isParent = $li.children('ul.sub-menu').length > 0;
648        let $all = $ov.find('a:visible');
649        let idx = $all.index(this);
650
651        if ([13, 32].includes(key)) {
652            e.preventDefault();
653            if (isParent) {
654                toggleSubmenu($link, $link.attr('aria-expanded') == 'false');
655            } else {
656                location.href = $link.attr('href');
657            }
658        } else if (key === 27) {
659            const $visibleSubmenus = $ov.find('ul.sub-menu:visible').filter(function() {
660                return $(this).css('display') !== 'none';
661            });
662
663            if ($visibleSubmenus.length > 0) {
664                const $deepestSubmenu = $visibleSubmenus.sort((a, b) => {
665                    return $(a).parents('ul.sub-menu').length - $(b).parents('ul.sub-menu').length;
666                }
666).last();
667
668                const $parentLi = $deepestSubmenu.parent('li');
669                const $parentLink = $parentLi.children('a');
670
671                $deepestSubmenu.slideUp().attr('aria-hidden', 'true');
672                $parentLink.attr('aria-expanded', 'false');
673                $deepestSubmenu.find('*').off('keydown.trap');
674                $parentLink.focus();
675            } else {
676                closeOverflow();
677            }
678            e.preventDefault();
679        } else if (key === 37) {
680            e.preventDefault();
681            const $submenu = $link.closest('ul.sub-menu');
682            const $allMain = $ov.find('.ofMenu > ul > li > a:visible');
683
684            if ($submenu.length > 0) {
685                const $parentLi = $submenu.parent('li');
686                const $parentLink = $parentLi.children('a');
687                $submenu.slideUp().attr('aria-hidden', 'true');
688                $parentLink.attr('aria-expanded', 'false');
689                $parentLink.focus();
690            } else {
691                const prev = (idx - 1 + $all.length) % $all.length;
692                $all.eq(prev).focus();
693            }
694        } else if (key === 39) {
695            e.preventDefault();
696            const $submenu = $link.closest('ul.sub-menu');
697            const $allMain = $ov.find('.ofMenu > ul > li > a:visible');
698
699            if ($submenu.length > 0) {
700                const $parentLi = $submenu.parent('li');
701                const $parentLink = $parentLi.children('a');
702                $submenu.slideUp().attr('aria-hidden', 'true');
703                $parentLink.attr('aria-expanded', 'false');
704                const mainIdx = $allMain.index($parentLink);
705                const nextIdx = (mainIdx + 1) % $allMain.length;
706                $allMain.eq(nextIdx).focus();
707            } else {
708                const next = (idx + 1) % $all.length;
709                $all.eq(next).focus();
710            }
711        } else if (key === 36) {
712            e.preventDefault();
713            $all.first().focus();
714        } else if (key === 35) {
715            e.preventDefault();
716            $all.last().focus();
717        }
718    });
719
720    $(document).on('click', function(e) {
721        if ($ov.is(':visible') && !$(e.target).closest('#overflowMenu, .moreNav').length) {
722            closeOverflow();
723        }
724    });
725
726    $(window).on('unload', function () {
727        $ov.hide().css('right', -ovWidth);
728        $ov.find('.sub-menu').hide().attr('aria-hidden', 'true');
729        $ov.find('a').attr('tabindex', -1);
730        $ov.find('[aria-expanded="true"]').attr('aria-expanded', 'false');
731    });
732
733    // Append HTML in body for screen reader purpose only 
734    if ($('#menu-status').length === 0) {
735    $('body').append('<div id="menu-status" role="status" aria-live="polite" style="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;"></div>');
736    }
737
738    // overflow menu expand/collapse message for screen reader
739    function announceMenuStatus(message) {
740    const $status = $('#menu-status');
741    $status.text(''); // Clear first to force re-announcement
742    setTimeout(() => $status.text(message), 10); 
743    }
744
745
746});
747
748//Add aria-modal and role dialog attr on mobile menu wrapper 
749jQuery(document).ready(function($) {
750  function updateMenuWrapperAttrs() {
751  if($(window).width()< 640){
752  
753  const mobileMenuOpen = $(".menuToggle").hasClass("clicked");
754  
755  $(".menuWrapper")
756  .attr("aria-hidden", mobileMenuOpen ? "false": "true")
757  }
758  else{
759  $(".menuWrapper")
760  .removeAttr("aria-hidden")
761  }
762  
763  }
764  
765   updateMenuWrapperAttrs();
766  $(window).on("resize", updateMenuWrapperAttrs );
767    $(".menuToggle").on("click", function(e) {
768      setTimeout (updateMenuWrapperAttrs, 10)
769    });
770  
771  });
772
773
774
775
776// code to handle menulink having link & submenu both  for desktop and keyboard Navigation start
777
778    jQuery(document).ready(function ($) {
779
780        $(".menuWrapper nav li.menu-item-has-children > a").on("keydown.realLinkFix", function (e) {
781
782            const $link = $(this);
783            const href = $link.attr("href") || "";
784            const isRealLink = href !== "#" && !href.startsWith("javascript");
785
786            if (isRealLink && (e.key === "Enter" || e.key === " ")) {
787                e.stopImmediatePropagation();
788                return true;
789            }
790
791        });
792            //Menu hints text announcement for screen reader code start
793                if ($("#menu-hint-global").length === 0) {
794                    $("body").append(
795                        '<div id="menu-hint-global" aria-live="polite" role="status" ' +
796                        'style="position:absolute;
796left:-9999px;top:-9999px;width:1px;height:1px;overflow:hidden;"></div>'
797                    );
798                }
799
800                const MENU_HINT_TEXT = "Press Enter to open the link. Press Down Arrow to open the submenu.";
801
802               $(".menuWrapper nav li.menu-item-has-children > a")
803                    .on("focus.realHint", function () {
804
805                        const $link = $(this);
806                        const href = $link.attr("href") || "";
807                        const isRealLink = href !== "#" && !href.startsWith("javascript");
808
809                        if (!isRealLink) return;
810
811                        $link.find(".menu-real-link-hint-wrapper").remove();
812
813                        setTimeout(function () {
814
815                            const inlineHintText = $(
816                                '<span class="menu-real-link-hint-wrapper" aria-live="polite" ' + 'style="position:absolute;left:-9999px;top:-9999px;">' +
817                                    '<span class="menu-real-link-hint">' + MENU_HINT_TEXT + '</span>' +
818                                '</span>'
819                            );
820                            $link.append(inlineHintText);
821                            const $globalMenuHint = $("#menu-hint-global");
822                            $globalMenuHint.text("");
823                            setTimeout(function () {
824                                $globalMenuHint.text(MENU_HINT_TEXT);
825                            }, 50);
826
827                        }, 300); 
828
829                    })
830                    .on("blur.realHint", function () {
831                        const $link = $(this);
832                        $link.find(".menu-real-link-hint-wrapper").remove();
833
834                        $("#menu-hint-global").text("");
835                    });
836
837          
838
839        // Handelling menu links with link as well as submenu  in mobile device js start
840           
841
842            // let lastInputType = "mouse"; 
843            // let lastTouchedLink = null;
844
845            // $(document)
846            //     .on("keydown.inputMode", function () {
847            //     lastInputType = "keyboard";
848            //     })
849            //     .on("touchstart.inputMode pointerdown.inputMode", function () {
850            //     lastInputType = "touch";
851            //     })
852            //     .on("mousedown.inputMode", function () {
853            //     lastInputType = "mouse";
854            //     });
855
856            // /* TOUCH-ONLY MENU LOGIC */
857            // $(".menuWrapper nav li.menu-item-has-children > a")
858            //     .on("click.touchMenu", function (e) {
859
860            //     //  If keyboard is being used → behave like desktop
861            //     if (lastInputType === "keyboard") return;
862
863            //     const $link = $(this);
864            //     const href = $link.attr("href") || "";
865            //     const isRealLink = href !== "#" && !href.startsWith("javascript");
866            //     const $parentLi = $link.parent("li");
867
868            //     if (!isRealLink) return;
869
870            //     // First touch → open submenu
871            //     if (!$parentLi.hasClass("submenu-open")) {
872            //         e.preventDefault();
873
874            //         $(".menuWrapper nav li.submenu-open")
875            //         .removeClass("submenu-open");
876
877            //         $parentLi.addClass("submenu-open");
878            //         lastTouchedLink = this;
879            //         return;
880            //     }
881
882            //     // Second touch on same link → allow navigation
883            //     if (lastTouchedLink === this) {
884            //         lastTouchedLink = null;
885            //         return true;
886            //     }
887
888            //     });
889
890            // /* TOUCHED OUTSIDE CLOSE SUBMENU */
891            // $(document).on("touchstart", function (e) {
892            //     if (!$(e.target).closest(".menuWrapper").length) {
893            //     $(".menuWrapper nav li.submenu-open").removeClass("submenu-open");
894            //     lastTouchedLink = null;
895            //     }
896            // });
897
898             // Handelling menu links with link as well as submenu  in mobile device js ends
899    });
900    
901// code to handle menulink having link & submenu both  for desktop and ke
901yboard Navigation end
902
903
904//handle esc key functionality js start 
905
906jQuery(document).ready(function ($) {
907
908    $(document).on('keydown.overflowEscHandler', function (e) {
909
910        if (e.key === "Escape" || e.keyCode === 27) {
911
912            const $ov = $('#overflowMenu');
913
914            // run only if overflow menu is open
915            if ($ov.is(':visible')) {
916
917                // if focus is inside overflow menu → let existing logic handle it
918                if ($(document.activeElement).closest('#overflowMenu').length) {
919                    return;
920                }
921
922                // otherwise close overflow
923                e.preventDefault();
924
925                const ovWidth = $ov.width();
926
927                $ov.animate({ right: -ovWidth }, 400, function () {
928                    $ov.css('display', 'none');
929                    $ov.find('a').attr('tabindex', -1);
930                    $('.moreNav > a').attr('aria-expanded', 'false').focus();
931                });
932
933            }
934
935        }
936
937    });
938
939});
940
941//handle esc key functionality js ends
942

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.