PageSourceSearch

https://dropwater.gr/wp-content/plugins/megamenu/js/maxmegamenu.js?ver=3.9.2.1

js dropwater.gr collected 2026-09-24 14:22:35 UTC 46,871 bytes, 1,096 lines download raw bytes

1/*jslint browser: true, white: true, this: true, long: true */
2/*global console,jQuery,megamenu,window,navigator*/
3
4/*! Max Mega Menu jQuery Plugin */
5(function ( $ ) {
6    "use strict";
7
8    let instanceCounter = 0;
9
10    $.maxmegamenu = function(menu, options) {
11
12        // --- DOM references ---
13        const plugin       = this;
14        const $menu        = $(menu);
15        const $wrap        = $menu.parent();
16        const $toggle_bar  = $menu.siblings(".mega-menu-toggle");
17
18        // --- Instance identifiers ---
19        const menuId            = $menu.attr("id");
20        const instanceId        = menuId + '-' + (++instanceCounter);
21        const docEventNamespace = '.megamenu-' + instanceId;
22
23        // --- Cached element sets (captured at init) ---
24        const items_with_submenus = $([
25            "li.mega-menu-megamenu.mega-menu-item-has-children",
26            "li.mega-menu-flyout.mega-menu-item-has-children",
27            "li.mega-menu-tabbed > ul.mega-sub-menu > li.mega-menu-item-has-children",
28            "li.mega-menu-flyout li.mega-menu-item-has-children"
29        ].join(","), $menu);
30
31        const collapse_children_parents = $("li.mega-menu-megamenu li.mega-menu-item-has-children.mega-collapse-children > a.mega-menu-link", $menu);
32
33        // --- Keyboard key identifiers (KeyboardEvent.key values) ---
34        const tab_key         = "Tab";
35        const escape_key      = "Escape";
36        const enter_key       = "Enter";
37        const space_key       = " ";
38        const left_arrow_key  = "ArrowLeft";
39        const up_arrow_key    = "ArrowUp";
40        const right_arrow_key = "ArrowRight";
41        const down_arrow_key  = "ArrowDown";
42
43        // --- Settings defaults (read from data attributes) ---
44        const defaults = {
45            event:                $menu.attr("data-event"),
46            effect:               $menu.attr("data-effect"),
47            effect_speed:         parseInt($menu.attr("data-effect-speed")),
48            effect_mobile:        $menu.attr("data-effect-mobile"),
49            effect_speed_mobile:  parseInt($menu.attr("data-effect-speed-mobile")),
50            panel_width:          $menu.attr("data-panel-width"),
51            panel_inner_width:    $menu.attr("data-panel-inner-width"),
52            mobile_force_width:   $menu.attr("data-mobile-force-width"),
53            mobile_overlay:       $menu.attr("data-mobile-overlay"),
54            mobile_state:         $menu.attr("data-mobile-state"),
55            mobile_direction:     $menu.attr("data-mobile-direction"),
56            second_click:         $menu.attr("data-second-click"),
57            vertical_behaviour:   $menu.attr("data-vertical-behaviour"),
58            document_click:       $menu.attr("data-document-click"),
59            breakpoint:           $menu.attr("data-breakpoint"),
60            unbind_events:        $menu.attr("data-unbind"),
61            hover_intent_timeout: $menu.attr("data-hover-intent-timeout") ?? 300,
62            hover_intent_interval: $menu.attr("data-hover-intent-interval") ?? 100
63        };
64
65        // --- Mutable state ---
66        plugin.settings = {};
67        let html_body_class_timeout;
68
69        plugin.addAnimatingClass = function(element) {
70            if (plugin.settings.effect === "disabled") {
71                return;
72            }
73
74            $(".mega-animating", $wrap).removeClass("mega-animating");
75
76            const timeout = plugin.settings.effect_speed + parseInt(plugin.settings.hover_intent_timeout, 10);
77
78            element.addClass("mega-animating");
79
80            setTimeout(function() {
81               element.removeClass("mega-animating");
82            }, timeout );
83        };
84
85        plugin.hideAllPanels = function() {
86            $(".mega-toggle-on > a.mega-menu-link", $menu).each(function() {
87                plugin.hidePanel($(this), false);
88            });
89        };
90
91        plugin.expandMobileSubMenus = function() {
92            if (plugin.settings.mobile_direction !== 'vertical') {
93                return;
94            }
95            
96            $(".mega-menu-item-has-children.mega-expand-on-mobile > a.mega-menu-link", $menu).each(function() {
97                plugin.showPanel($(this), true);
98            });
99
100            if ( plugin.settings.mobile_state === 'expand_all' ) {
101                $(".mega-menu-item-has-children:not(.mega-toggle-on) > a.mega-menu-link", $menu).each(function() {
102                    plugin.showPanel($(this), true);
103                });
104            }
105
106            if ( plugin.settings.mobile_state === 'expand_active' ) {
107                const activeItemSelectors = [
108                    "li.mega-current-menu-ancestor.mega-menu-item-has-children > a.mega-menu-link",
109                    "li.mega-current-menu-item.mega-menu-item-has-children > a.mega-menu-link",
110                    "li.mega-current-menu-parent.mega-menu-item-has-children > a.mega-menu-link",
111                    "li.mega-current_page_ancestor.mega-menu-item-has-children > a.mega-menu-link",
112                    "li.mega-current_page_item.mega-menu-item-has-children > a.mega-menu-link"
113                ];
114
115                $menu.find(activeItemSelectors.join(', ')).each(function() {
116                    plugin.showPanel($(this), true);
117                });
118            }
119        };
120
121        plugin.hideSiblingPanels = function(anchor, immediate) {
122            anchor.parent().parent().find(".mega-toggle-on").children("a.mega-menu-link").each(function() { // all open children of open siblings
123                plugin.hidePanel($(this), immediate);
124            });
125        };
126
127        plugin.isDesktopView = function() {
128            const width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
129            return width > plugin.settings.breakpoint;
130        };
131
132        plugin.isMobileView = function() {
133            return !plugin.isDesktopView();
134        };
135
136        plugin.isHorizontalMobileSubmenuMode = function() {
137            return plugin.isMobileView() && plugin.isMobileOffCanvas() && plugin.settings.mobile_direction === "horizontal";
138        };
139
140        plugin.getFocusableItemsInSubmenu = function($submenu, include_back_link = true) {
141            let $focusable = $submenu.children("li.mega-menu-item:visible").find("> a.mega-menu-link, > .mega-search span[role=button]");
142
143            if (!include_back_link) {
144                $focusable = $focusable.not(".mega-mobile-back-link");
145            }
146
147            return $focusable;
148        };
149
150        plugin.focusFirstItemInOpenedSubmenu = function($item) {
151            if ( ! plugin.isHorizontalMobileSubmenuMode() || ! $wrap.hasClass("mega-keyboard-navigation")) {
152                return;
153            }
154
155            const $submenu = $item.children("ul.mega-sub-menu");
156
157            if (!$submenu.length) {
158                return;
159            }
160
161            const $firstFocusable = plugin.getFocusableItemsInSubmenu($submenu, false).first();
162
163            if ($firstFocusable.length) {
164                $firstFocusable.trigger("focus");
165            }
166        };
167
168        plugin.deferFocusFirstItemInOpenedSubmenu = function($item) {
169            const delay = Math.min(120, parseInt(plugin.settings.effect_speed_mobile, 10) || 0);
170
171            setTimeout(function() {
172                plugin.focusFirstItemInOpenedSubmenu($item);
173
174                // Retry once after the first paint in case CSS visibility/transform has not applied yet.
175                setTimeout(function() {
176                    const focusedInSubmenu = $item.find("ul.mega-sub-menu").has(document.activeElement).length !== 0;
177
178                    if (!focusedInSubmenu) {
179                        plugin.focusFirstItemInOpenedSubmenu($item);
180                    }
181                }, 40);
182            }, delay);
183        };
184
185        plugin.showPanel = function(anchor, immediate) {
186            if ( typeof anchor === 'number' || ( typeof anchor === 'string' && anchor.trim() !== '' && !isNaN(anchor) ) ) {
187                anchor = $("li.mega-menu-item-" + anchor, $menu).find("a.mega-menu-link").first();
188            } else if ( anchor.is("li.mega-menu-item") ) {
189                anchor = anchor.find("a.mega-menu-link").first();
190            }
191
192            const $item = anchor.parent();
193            const isDesktop = plugin.isDesktopView();
194            const isMobile = !isDesktop;
195
196            $item.triggerHandler("before_open_panel");
197
198            $item.find("[aria-expanded]").first().attr("aria-expanded", "true");
199
200            $(".mega-animating", $wrap).removeClass("mega-animating");
201
202            if (isMobile && $item.hasClass("mega-hide-sub-menu-on-mobile")) {
203                return;
204            }
205
206            if (isDesktop && ( $menu.hasClass("mega-menu-horizontal") || $menu.hasClass("mega-menu-vertical") ) && !$item.hasClass("mega-collapse-children")) {
207                plugin.hideSiblingPanels(anchor, true);
208            }
209
210            if ((isMobile && $wrap.hasClass("mega-keyboard-navigation")) || plugin.settings.vertical_behaviour === "accordion") {
211                plugin.hideSiblingPanels(anchor, false);
212            }
213
214            plugin.calculateDynamicSubmenuWidths(anchor);
215
216            // apply jQuery transition (only if the effect is set to "slide", other transitions are CSS based)
217            if ( plugin.shouldUseSlideAnimation(anchor, immediate) ) {
218                const speed = isMobile ? plugin.settings.effect_speed_mobile : plugin.settings.effect_speed;
219
220                anchor.siblings(".mega-sub-menu").css("display", "none").animate({"height":"show", "paddingTop":"show", "paddingBottom":"show", "minHeight":"show"}, speed, function() {
221                    $(this).css("display", "");
222                });
223            }
224
225            $item.addClass("mega-toggle-on").triggerHandler("open_panel");
226            plugin.deferFocusFirstItemInOpenedSubmenu($item);
227        };
228        
229
230        plugin.shouldUseSlideAnimation = function(anchor, immediate) {
231
232            if (immediate === true) {
233                return false;
234            }
235
236            if (anchor.parent().hasClass("mega-collapse-children")) {
237                return true;
238            }
239
240            const isDesktop = plugin.isDesktopView();
241
242            if (isDesktop && plugin.settings.effect === "slide") {
243                return true;
244            }
245
246            if (!isDesktop) {
247                if (plugin.settings.effect_mobile === "slide") {
248                    return true;
249                }
250
251                if ( plugin.isMobileOffCanvas() ) {
252                    return plugin.settings.mobile_direction !== "horizontal";
253                }
254            }
255
256            return false;
257        };
258
259
260        plugin.hidePanel = function(anchor, immediate) {
261            if ( typeof anchor === 'number' || ( typeof anchor === 'string' && anchor.trim() !== '' && !isNaN(anchor) ) ) {
262                anchor = $("li.mega-menu-item-" + anchor, $menu).find("a.mega-menu-link").first();
263            } else if ( anchor.is("li.mega-menu-item") ) {
264                anchor = anchor.find("a.mega-menu-link").first();
265            }
266
267            const $item = anchor.parent();
268            const $submenu = anchor.siblings(".mega-sub-menu");
269            const isMobile = plugin.isMobileView();
270
271            $item.triggerHandler("before_close_panel");
272
273            $item.find("[aria-expanded]").first().attr("aria-expanded", "false");
274
275            if ( plugin.shouldUseSlideAnimation(anchor) ) {
276                const speed = isMobile ? plugin.settings.effect_speed_mobile : plugin.settings.effect_speed;
277
278                $submenu.animate({"height":"hide", "paddingTop":"hide", "paddingBottom":"hide", "minHeight":"hide"}, speed, function() {
279                    $submenu.css("display", "");
280                    $item.removeClass("mega-toggle-on").triggerHandler("close_panel");
281                });
282
283                return;
284            }
285
286            if (immediate) {
287                $submenu.css("display", "none").delay(plugin.settings.effect_speed).queue(function(){
288                    $(this).css("display", "").dequeue();
289                });
290            }
291
292            // pause video widget videos
293            $submenu.find(".widget_media_video video").each(function() {
294                if ( this.player ) {
295                    this.player.pause();
296                }
297            });
298
299            $item.removeClass("mega-toggle-on").triggerHandler("close_panel");
300            plugin.addAnimatingClass($item);
301        };
302
303        plugin.calculateDynamicSubmenuWidths = function(anchor) {
304            const $item = anchor.parent();
305            const $submenu = anchor.siblings(".mega-sub-menu");
306            const isDesktop = plugin.isDesktopView();
307            const isTopLevelMegamenu = $item.hasClass("mega-menu-megamenu") && $item.parent().hasClass("max-mega-menu");
308
309            // apply dynamic width and sub menu position (only to top level mega menus)
310            if (isTopLevelMegamenu && plugin.settings.panel_width) {
311                if (isDesktop) {
312                    const submenu_offset = $menu.offset();
313
314                    if ( plugin.settings.panel_width === '100vw' ) {
315                        const target_offset = $('body').offset();
316
317                        $submenu.css({
318                            left: (target_offset.left - submenu_offset.left) + "px"
319                        });
320                    } else {
321                        const $panel_width_el = $(plugin.settings.panel_width);
322
323                        if ( $panel_width_el.length > 0 ) {
324                            $submenu.css({
325                                width: $panel_width_el.outerWidth(),
326                                left: ($panel_width_el.offset().left - submenu_offset.left) + "px"
327                            });
328                        }
329                    }
330                } else {
331                    $submenu.css({
332                        width: "",
333                        left: ""
334                    });
335                }
336            }
337
338            // apply inner width to sub menu by adding padding to the left and right of the mega menu
339            if (isTopLevelMegamenu && plugin.settings.panel_inner_width) {
340                const $panel_inner_width_el = $(plugin.settings.panel_inner_width);
341
342                if ($panel_inner_width_el.length > 0) {
343                    const target_width = parseInt($panel_inner_width_el.width(), 10);
344
345                    $submenu.css({
346                        "paddingLeft": "",
347                        "paddingRight": ""
348                    });
349
350                    const submenu_width = parseInt($submenu.innerWidth(), 10);
351
352                    if (isDesktop && target_width > 0 && target_width < submenu_width) {
353                        $submenu.css({
354                            "paddingLeft": (submenu_width - target_width) / 2 + "px",
355                            "paddingRight": (submenu_width - target_width) / 2 + "px"
356                        });
357                    }
358                }
359            }
360        };
361
362        plugin.bindClickEvents = function() {
363
364            plugin.unbindClickEvents();
365
366            let dragging = false;
367
368            $(document).on({
369                ["touchmove" + docEventNamespace]: function() { dragging = true; },
370                ["touchstart" + docEventNamespace]: function() { dragging = false; }
371            });
372
373            $(document).on("click" + docEventNamespace + " touchend" + docEventNamespace, function(e) { // hide menu when clicked away from
374                if (!dragging && plugin.settings.document_click === "collapse" && ! $(e.target).closest(".mega-menu-wrap").length ) {
375                    plugin.hideAllPanels();
376                    plugin.hideMobileMenu();
377                }
378                dragging = false;
379            });
380
381            const clickable_parents = $("> a.mega-menu-link", items_with_submenus).add(collapse_children_parents);
382
383            clickable_parents.on("touchend.megamenu", function(e) {
384                if (plugin.settings.event === "hover_intent") {
385                    plugin.unbindHoverIntentEvents();
386                }
387
388                if (plugin.settings.event === "hover") {
389                    plugin.unbindHoverEvents();
390                }
391            });
392
393            clickable_parents.on("click.megamenu", function(e) {
394                if ( $(e.target).hasClass('mega-indicator') ) {
395                    return;
396                }
397
398                if (plugin.isDesktopView() && $(this).parent().hasClass("mega-toggle-on") && $(this).closest("ul.mega-sub-menu").parent().hasClass("mega-menu-tabbed") ) {
399                    if (plugin.settings.second_click === "go") {
400                        return;
401                    } else {
402                        e.preventDefault();
403                        return;
404                    }
405                }
406                if (dragging) {
407                    return;
408                }
409                if (plugin.isMobileView() && $(this).parent().hasClass("mega-hide-sub-menu-on-mobile")) {
410                    return; // allow all clicks on parent items when sub menu is hidden on mobile
411                }
412                if ((plugin.settings.second_click === "go" || $(this).parent().hasClass("mega-click-click-go")) && $(this).attr("href") !== undefined) { // check for second click
413                    if (!$(this).parent().hasClass("mega-toggle-on")) {
414                        e.preventDefault();
415                        plugin.showPanel($(this));
416                    }
417                } else {
418                    e.preventDefault();
419
420                    if ($(this).parent().hasClass("mega-toggle-on")) {
421                        plugin.hidePanel($(this), false);
422                    } else {
423                        plugin.showPanel($(this));
424                    }
425                }
426            });
427
428            if ( plugin.settings.second_click === "disabled" ) {
429                clickable_parents.off("click.megamenu");
430            }
431
432            $(".mega-close-after-click:not(.mega-menu-item-has-children) > a.mega-menu-link", $menu).on("click.megamenu", function() {
433                plugin.hideAllPanels();
434                plugin.hideMobileMenu();
435            });
436
437            $("button.mega-close", $wrap).on("click.megamenu", function(e) {
438                plugin.hideMobileMenu();
439            });
440        };
441
442        plugin.bindHoverEvents = function() {
443            items_with_submenus.on({
444                "mouseenter.megamenu" : function() {
445                    plugin.unbindClickEvents();
446                    if (! $(this).hasClass("mega-toggle-on")) {
447                        plugin.showPanel($(this).children("a.mega-menu-link"));
448                    }
449                },
450                "mouseleave.megamenu" : function() {
451                    if ($(this).hasClass("mega-toggle-on") && ! $(this).hasClass("mega-disable-collapse") && ! $(this).parent().parent().hasClass("mega-menu-tabbed")) {
452                        plugin.hidePanel($(this).children("a.mega-menu-link"), false);
453                    }
454                }
455            });
456        };
457
458        plugin.bindHoverIntentEvents = function() {
459            items_with_submenus.hoverIntent({
460                over: function () {
461                    plugin.unbindClickEvents();
462                    if (! $(this).hasClass("mega-toggle-on")) {
463                        plugin.showPanel($(this).children("a.mega-menu-link"));
464                    }
465                },
466                out: function () {
467                    if ($(this).hasClass("mega-toggle-on") && ! $(this).hasClass("mega-disable-collapse") && ! $(this).parent().parent().hasClass("mega-menu-tabbed")) {
468                        plugin.hidePanel($(this).children("a.mega-menu-link"), false);
469                    }
470                },
471                timeout: plugin.settings.hover_intent_timeout,
472                interval: plugin.settings.hover_intent_interval
473            });
474        };
475
476        plugin.isMobileOffCanvas = function() {
477            return plugin.settings.effect_mobile === 'slide_left' || plugin.settings.effect_mobile === 'slide_right';
478        };
479
480        plugin.shouldGoToNextTopLevelItem = function(key) {
481            return ( ( key === right_arrow_key && plugin.isDesktopView() ) || ( key === down_arrow_key && plugin.isMobileView() ) ) && $menu.hasClass("mega-menu-horizontal");
482        };
483
484        plugin.shouldGoToPreviousTopLevelItem = function(key) {
485            return ( ( key === left_arrow_key && plugin.isDesktopView() ) || ( key === up_arrow_key && plugin.isMobileView() ) ) && $menu.hasClass("mega-menu-horizontal");
486        };
487
488        plugin.bindKeyboardEvents = function() {
489            const $firstFocusable = $menu.find("a.mega-menu-link").first();
490            const $lastFocusable = $wrap.find("button.mega-close").first();
491
492            const isMobileOffCanvasHorizontal = function() {
493                return plugin.isHorizontalMobileSubmenuMode();
494            };
495
496            const getActiveHorizontalSubmenuBackLink = function() {
497                const $activeSubmenu = $("li.mega-toggle-on > ul.mega-sub-menu", $menu).last();
498                return $activeSubmenu.find("> li.mega-mobile-back:visible > a.mega-menu-link.mega-mobile-back-link").first();
499            };
500
501            const shouldTrapFocusInCurrentSubMenu = function(key) {
502                return isMobileOffCanvasHorizontal() && ( key === up_arrow_key || key === down_arrow_key );
503            };
504            const togglePanelForAnchor = function(anchor) {
505                if ( !anchor || !anchor.length ) {
506                    return;
507                }
508
509                if ( anchor.parent().hasClass("mega-toggle-on") && ! anchor.closest("ul.mega-sub-menu").parent().hasClass("mega-menu-tabbed") ) {
510                    plugin.hidePanel(anchor);
511                } else {
512                    plugin.showPanel(anchor);
513                }
514            };
515            const closeNearestOpenPanelAndRefocus = function() {
516                const focused_menu_item = $menu[0].contains(document.activeElement) ? $(document.activeElement) : $();
517                const nearest_parent_of_focused_item_li = focused_menu_item.closest(".mega-toggle-on");
518                const nearest_parent_of_focused_item_a = $("> a.mega-menu-link", nearest_parent_of_focused_item_li);
519
520                if ( nearest_parent_of_focused_item_a.length ) {
521                    plugin.hidePanel(nearest_parent_of_focused_item_a);
522                    nearest_parent_of_focused_item_a.trigger("focus");
523                    return true;
524                }
525
526                return false;
527            };
528
529            $lastFocusable.on('keydown.megamenu', function(e) {
530                const key = e.key;
531
532                if ( plugin.isMobileView() && plugin.isMobileOffCanvas() && key === tab_key && ! e.shiftKey ) {
533                    e.preventDefault();
534                    if ( isMobileOffCanvasHorizontal() ) {
535                        const $backLink = getActiveHorizontalSubmenuBackLink();
536
537                        if ( $backLink.length ) {
538                            $backLink.trigger('focus');
539                            return;
540                        }
541                    }
542
543                    $firstFocusable.trigger('focus');
544                }
545
546                if ( plugin.isMobileView() && plugin.isMobileOffCanvas() && key === tab_key && e.shiftKey && isMobileOffCanvasHorizontal() ) {
547                    const $activeSubmenu = $("li.mega-toggle-on > ul.mega-sub-menu", $menu).last();
548                    const $focusableWithoutBack = plugin.getFocusableItemsInSubmenu($activeSubmenu, false);
549                    const $lastFocusableInSubmenu = $focusableWithoutBack.last();
550
551                    if ( $lastFocusableInSubmenu.length ) {
552                        e.preventDefault();
553                        $lastFocusableInSubmenu.trigger('focus');
554                    }
555                }
556            });
557
558            $firstFocusable.on('keydown.megamenu', function(e) {
559                const key = e.key;
560
561                if ( plugin.isMobileView() && plugin.isMobileOffCanvas() && key === tab_key && e.shiftKey) {
562                    e.preventDefault();
563                    $lastFocusable.trigger('focus');
564                }
565            });
566
567            $wrap.on("keyup.megamenu", ".max-mega-menu, .mega-menu-toggle", function(e) {
568                const key = e.key;
569                const active_link = $(e.target);
570
571                if (key === tab_key) {
572                    $wrap.addClass("mega-keyboard-navigation");
573                    plugin.bindClickEvents(); // Windows Narrator ignores the Enter keypress, so ensure click events are available when pressing tab
574
575                    if ( plugin.isDesktopView() && active_link.is(".mega-menu-link") && active_link.parent().parent().hasClass('max-mega-menu') ) {
576                        plugin.hideAllPanels();
577                    }
578                }
579            });
580
581            $wrap.on("keydown.megamenu", "a.mega-menu-link, .mega-indicator, .mega-menu-toggle-block, .mega-menu-toggle-animated-block button, button.mega-close", function(e) {
582
583                if ( ! $wrap.hasClass("mega-keyboard-navigation") ) {
584                    return;
585                }
586
587                const key = e.key;
588                const active_link = $(e.target);
589
590                if ( isMobileOffCanvasHorizontal() && key === tab_key && !e.shiftKey ) {
591                    const $submenu = active_link.closest("ul.mega-sub-menu");
592
593                    if ( $submenu.length !== 0 ) {
594                        const $focusableWithoutBack = plugin.getFocusableItemsInSubmenu($submenu, false);
595
596                        if ( $focusableWithoutBack.length !== 0 && active_link.is($focusableWithoutBack.last()) ) {
597                            e.preventDefault();
598                            $lastFocusable.trigger("focus");
599                            return;
600                        }
601                    }
602                }
603
604                if ( isMobileOffCanvasHorizontal() && key === tab_key && e.shiftKey ) {
605                    const $submenu = active_link.closest("ul.mega-sub-menu");
606
607                    if ( $submenu.length !== 0 && active_link.hasClass("mega-mobile-back-link") ) {
608                        e.preventDefault();
609                        $lastFocusable.trigger("focus");
610                        return;
611                    }
612
613                    if ( $submenu.length !== 0 ) {
614                        const $focusableWithoutBack = plugin.getFocusableItemsInSubmenu($submenu, false);
615                        const $firstFocusableInSubmenu = $focusableWithoutBack.first();
616                        const $backLink = $submenu.find("> li.mega-mobile-back:visible > a.mega-menu-link.mega-mobile-back-link").first();
617
618                        if ( $firstFocusableInSubmenu.length !== 0 && $backLink.length !== 0 && active_link.is($firstFocusableInSubmenu) ) {
619                            e.preventDefault();
620                            $backLink.trigger("focus");
621                            return;
622                        }
623                    }
624                }
625
626                if ( key === space_key && active_link.is(".mega-menu-link") ) {
627                    e.preventDefault();
628
629                    // pressing space on a parent item will always toggle the sub menu
630                    if ( active_link.parent().is(items_with_submenus) ) {
631                        togglePanelForAnchor(active_link);
632                    }
633                }
634
635                if ( key === space_key && active_link.is(".mega-indicator") ) {
636                    e.preventDefault();
637                    togglePanelForAnchor(active_link.parent());
638                }
639
640                if ( key === escape_key ) {
641                    const submenu_open = $(".mega-toggle-on", $menu).length !== 0;
642
643                    if ( submenu_open && closeNearestOpenPanelAndRefocus() ) {
644                        return;
645                    }
646
647                    if ( plugin.isMobileView() && ! submenu_open ) {
648                        plugin.hideMobileMenu();
649                    }
650                }
651
652                if ( key === space_key || key === enter_key ) {
653                    if ( active_link.is(".mega-menu-toggle-block button, .mega-menu-toggle-animated-block button") ) {
654                        e.preventDefault();
655                        
656                        if ( $toggle_bar.hasClass("mega-menu-open") ) {
657                            plugin.hideMobileMenu();
658                        } else {
659                            plugin.showMobileMenu();
660
661                            html_body_class_timeout = setTimeout(function() {
662                                $menu.find("a.mega-menu-link").first().trigger('focus');
663                            }, plugin.settings.effect_speed_mobile);
664                        }
665                    }
666                }
667
668                if ( key === enter_key ) { // ignored by windows narrator
669
670                    // pressing enter on an arrow will toggle the sub menu
671                    if ( active_link.is(".mega-indicator") ) {
672                        togglePanelForAnchor(active_link.parent());
673
674                        return;
675                    }
676                    // pressing enter on a parent link
677                    if ( active_link.parent().is(items_with_submenus) ) {
678
679                        // when clicking on the parent of a hidden submenu, follow the link
680                        if ( plugin.isMobileView() && active_link.parent().is(".mega-hide-sub-menu-on-mobile") ) {
681                            return;
682                        }
683
684                        // pressing enter on a parent item without a link 
684will toggle the sub menu
685                        if ( active_link.is("[href]") === false ) {
686                            togglePanelForAnchor(active_link);
687
688                            return;
689                        }
690
691                        // pressing enter on a parent item will first open the sub menu, then follow the link
692                        if ( active_link.parent().hasClass("mega-toggle-on") && ! active_link.closest("ul.mega-sub-menu").parent().hasClass("mega-menu-tabbed") ) {
693                            return;
694                        } else {
695                            e.preventDefault();
696                            plugin.showPanel(active_link);
697                        }
698                    }
699                }
700
701                if ( shouldTrapFocusInCurrentSubMenu(key) ) {
702                    const focused_item = $menu[0].contains(document.activeElement) ? $(document.activeElement) : $();
703
704                    // if the menu doesn't have focus, focus the first menu item
705                    if ( focused_item.length === 0) {
706                        e.preventDefault();
707                        $("> li.mega-menu-item:visible", $menu).find("> a.mega-menu-link, .mega-search span[role=button]").first().trigger('focus');
708                        return;
709                    }
710
711                    // try to find the next item at the same level
712                    let next_item_to_focus = focused_item.parent().nextAll("li.mega-menu-item:visible").find("> a.mega-menu-link, .mega-search span[role=button]").first();
713
714                    // can't find another item in the same level, attempt to skip back to the top
715                    if ( next_item_to_focus.length === 0 && focused_item.closest(".mega-menu-megamenu").length !== 0 ) {
716                        // are we inside a megamenu? find the 'back' button and focus on that
717                        const all_li_parents = focused_item.parentsUntil(".mega-menu-megamenu");
718
719                        if ( focused_item.is(all_li_parents.find("a.mega-menu-link").last()) ) {
720                            next_item_to_focus = all_li_parents.find(".mega-back-button:visible > a.mega-menu-link").first();
721                        }
722                    }
723
724                    // skip back to the top of non-megamenu menus
725                    if ( next_item_to_focus.length === 0 ) {
726                        next_item_to_focus = focused_item.parent().prevAll("li.mega-menu-item:visible").find("> a.mega-menu-link, .mega-search span[role=button]").first();
727                    }
728
729                    if ( next_item_to_focus.length !== 0 ) {
730                        e.preventDefault();
731                        next_item_to_focus.trigger('focus');
732                    }
733                    
734                }
735
736                if ( plugin.shouldGoToNextTopLevelItem(key) ) {
737                    e.preventDefault();
738
739                    const $focused_next = $(document.activeElement);
740                    let next_top_level_item = $("> .mega-toggle-on", $menu).nextAll("li.mega-menu-item:visible").find("> a.mega-menu-link, .mega-search span[role=button]").first();
741
742                    if (next_top_level_item.length === 0) {
743                        next_top_level_item = $focused_next.parent().nextAll("li.mega-menu-item:visible").find("> a.mega-menu-link, .mega-search span[role=button]").first();
744                    }
745
746                    if (next_top_level_item.length === 0) {
747                        next_top_level_item = $focused_next.parent().parent().parent().nextAll("li.mega-menu-item:visible").find("> a.mega-menu-link, .mega-search span[role=button]").first();
748                    }
749
750                    plugin.hideAllPanels();
751                    next_top_level_item.trigger('focus');
752                }
753
754                if ( plugin.shouldGoToPreviousTopLevelItem(key) ) {
755                    e.preventDefault();
756
757                    const $focused_prev = $(document.activeElement);
758                    let prev_top_level_item = $("> .mega-toggle-on", $menu).prevAll("li.mega-menu-item:visible").find("> a.mega-menu-link, .mega-search span[role=button]").last();
759
760                    if (prev_top_level_item.length === 0) {
761                        prev_top_level_item = $focused_prev.parent().prevAll("li.mega-menu-item:visible").find("> a.mega-menu-link, .mega-search span[role=button]").last();
762                    }
763
764                    if (prev_top_level_item.length === 0) {
765                        prev_top_level_item = $focused_prev.parent().parent().parent().prevAll("li.mega-menu-item:visible").find("> a.mega-menu-link, .mega-search span[role=button]").last();
766                    }
767
768                    plugin.hideAllPanels();
769                    prev_top_level_item.trigger('focus');
770                }
771            });
772
773            $wrap.on("focusout.megamenu", function(e) {
774                if ( $wrap.hasClass("mega-keyboard-navigation") ) {
775                    setTimeout(function() {
776                        const menu_has_focus = $wrap[0].contains(document.activeElement);
777                        if (! menu_has_focus) {
778                            $wrap.removeClass("mega-keyboard-navigation");
779                            plugin.hideAllPanels();
780                            plugin.hideMobileMenu();
781                        }
782                    }, 10);
783                }
784            });
785        };
786
787        plugin.unbindAllEvents = function() {
788            $(document).off(docEventNamespace);
789            $("ul.mega-sub-menu, li.mega-menu-item, li.mega-menu-row, li.mega-menu-column, a.mega-menu-link, .mega-indicator", $menu).off();
790        };
791
792        plugin.unbindClickEvents = function() {
793            if ( $wrap.hasClass('mega-keyboard-navigation') ) {
794                return;
795            }
796
797            $(document).off(docEventNamespace);
798
799            // collapsable parents always have a click event
800            $("> a.mega-menu-link", items_with_submenus).not(collapse_children_parents).off("click.megamenu touchend.megamenu");
801        };
802
803        plugin.unbindHoverEvents = function() {
804            items_with_submenus.off("mouseenter.megamenu mouseleave.megamenu");
805        };
806
807        plugin.unbindHoverIntentEvents = function() {
808            items_with_submenus.off("mouseenter mouseleave").removeProp("hoverIntent_t").removeProp("hoverIntent_s"); // hoverintent does not allow namespaced events
809        };
810
811        plugin.unbindKeyboardEvents = function() {
812            $wrap.off("keyup.megamenu keydown.megamenu focusout.megamenu");
813        };
814
815        plugin.unbindMegaMenuEvents = function() {
816            if (plugin.settings.event === "hover_intent") {
817                plugin.unbindHoverIntentEvents();
818            }
819
820            if (plugin.settings.event === "hover") {
821                plugin.unbindHoverEvents();
822            }
823
824            plugin.unbindClickEvents();
825            plugin.unbindKeyboardEvents();
826        };
827
828        plugin.bindMegaMenuEvents = function() {
829            plugin.unbindMegaMenuEvents();
830
831            const isDesktop = plugin.isDesktopView();
832
833            if (isDesktop && plugin.settings.event === "hover_intent") {
834                plugin.bindHoverIntentEvents();
835            }
836
837            if (isDesktop && plugin.settings.event === "hover") {
838                plugin.bindHoverEvents();
839            }
840
841            plugin.bindClickEvents(); // always bind click events for touch screen devices
842            plugin.bindKeyboardEvents();
843        };
844
845        plugin.checkWidth = function() {
846            if ( plugin.isMobileView() && $menu.data("view") === "desktop" ) {
847                plugin.switchToMobile();
848            }
849
850            if ( plugin.isDesktopView() && $menu.data("view") === "mobile" ) {
851                plugin.switchToDesktop();
852            }
853
854            plugin.calculateDynamicSubmenuWidths($("> li.mega-menu-megamenu > a.mega-menu-link", $menu));
855        };
856
857        plugin.reverseRightAlignedItems = function() {
858            if ( ! $("body").hasClass("rtl") && $menu.hasClass("mega-menu-horizontal") && $menu.css("display") !== 'flex' ) {
859                $menu.append($menu.children("li.mega-item-align-right").get().reverse());
860            }
861        };
862
863        plugin.addClearClassesToMobileItems = function() {
864            $(".mega-menu-row", $menu).each(function() {
865                $("> .mega-sub-menu > .mega-menu-column:not(.mega-hide-on-mobile)", $(this)).filter(":even").addClass("mega-menu-clear"); // :even is 0 based
866            });
867        };
868
869        plugin.initDesktop = function() {
870            $menu.data("view", "desktop");
871            plugin.bindMegaMenuEvents();
872            plugin.initIndicators();
873        };
874
875        plugin.initMobile = function() {
876            plugin.switchToMobile();
877        };
878
879        plugin.switchToDesktop = function() {
880            $menu.data("view", "desktop");
881            plugin.bindMegaMenuEvents();
882            plugin.reverseRightAlignedItems();
883            plugin.hideAllPanels();
884            plugin.hideMobileMenu(true);
885            $menu.removeAttr('role');
886            $menu.removeAttr('aria-modal');
887            $menu.removeAttr('aria-hidden');
888        };
889
890        plugin.switchToMobile = function() {
891            $menu.data("view", "mobile");
892
893            if (plugin.isMobileOffCanvas() && $toggle_bar.is(":visible") ) {
894                $menu.attr('role', 'dialog');
895                $menu.attr('aria-modal', 'true');
896                $menu.attr('aria-hidden', 'true');
897            }
898
899            plugin.bindMegaMenuEvents();
900            plugin.initIndicators();
901            plugin.reverseRightAlignedItems();
902            plugin.addClearClassesToMobileItems();
903            plugin.hideAllPanels();
904            plugin.expandMobileSubMenus();
905
906        };
907
908        plugin.initToggleBar = function() {
909            $toggle_bar.on("click", function(e) {
910                if ( $(e.target).is(".mega-menu-toggle, .mega-menu-toggle-custom-block *, .mega-menu-toggle-block, .mega-menu-toggle-animated-block, .mega-menu-toggle-animated-block *, .mega-toggle-blocks-left, .mega-toggle-blocks-center, .mega-toggle-blocks-right, .mega-toggle-label, .mega-toggle-label span") ) {
911                    e.preventDefault();
912                    
913                    if ($(this).hasClass("mega-menu-open")) {
914                        plugin.hideMobileMenu();
915                    } else {
916                        plugin.showMobileMenu();
917                    }
918                }
919            });
920        };
921
922        plugin.initIndicators = function() {
923             $menu.off('click.megamenu', '.mega-indicator');
924
925             $menu.on('click.megamenu', '.mega-indicator', function(e) {
926                e.preventDefault();
927                e.stopPropagation();
928
929                if ( $(this).closest(".mega-menu-item").hasClass("mega-toggle-on") ) {
930                    if ( ! $(this).closest("ul.mega-sub-menu").parent().hasClass("mega-menu-tabbed") || plugin.isMobileView() ) {
931                        plugin.hidePanel($(this).parent(), false);
932                    }
933                } else {
934                    plugin.showPanel($(this).parent(), false);
935                }
936             });
937        };
938
939        plugin.hideMobileMenu = function(force = false) {
940
941            if ( ! $toggle_bar.is(":visible") && ! force ) {
942                return;
943            }
944
945            $menu.attr("aria-hidden", "true");
946
947            clearTimeout(html_body_class_timeout);
948            html_body_class_timeout = setTimeout(function() {
949                $("body").removeClass(menuId + "-mobile-open");
950                $("html").removeClass(menuId + "-off-canvas-open");
951            }, plugin.settings.effect_speed_mobile);
952
953            if ($wrap.hasClass("mega-keyboard-navigation")) {
954                $(".mega-menu-toggle-block button, button.mega-toggle-animated", $toggle_bar).first().trigger('focus');
955            }
956
957            $(".mega-toggle-label, .mega-toggle-animated", $toggle_bar).attr("aria-expanded", "false");
958
959            if (plugin.settings.effect_mobile === "slide" && ! force ) {
960                $menu.animate({"height":"hide"}, plugin.settings.effect_speed_mobile, function() {
961                    $menu.css({
962                        width: "",
963                        left: "",
964                        display: ""
965                    });
966
967                    $toggle_bar.removeClass("mega-menu-open");
968                });
969            } else {
970                $menu.css({
971                    width: "",
972                    left: "",
973                    display: ""
974                });
975                    
976                $toggle_bar.removeClass("mega-menu-open");
977            }
978
979            
980            $menu.triggerHandler("mmm:hideMobileMenu");
981        };
982
983        plugin.showMobileMenu = function() {
984            if ( ! $toggle_bar.is(":visible") ) {
985                return;
986            }
987
988            clearTimeout(html_body_class_timeout);
989
990            $("body").addClass(menuId + "-mobile-open");
991
992            plugin.expandMobileSubMenus();
993
994            if ( plugin.isMobileOffCanvas() ) {
995                $("html").addClass(menuId + "-off-canvas-open");
996            }
997
998            if (plugin.settings.effect_mobile === "slide") {
999                $menu.animate({"height":"show"}, plugin.settings.effect_speed_mobile, function() {
1000                    $(this).css("display", "");
1001                });
1002            }
1003
1004            $(".mega-toggle-label, .mega-toggle-animated", $toggle_bar).attr("aria-expanded", "true");
1005
1006            $toggle_bar.addClass("mega-menu-open");
1007
1008            plugin.toggleBarForceWidth();
1009
1010            $menu.attr("aria-hidden", "false");
1011            $menu.triggerHandler("mmm:showMobileMenu");
1012        };
1013
1014        plugin.toggleBarForceWidth = function() {
1015            const $force_width_el = $(plugin.settings.mobile_force_width);
1016
1017            if ($force_width_el.length && ( plugin.settings.effect_mobile === "slide" || plugin.settings.effect_mobile === "disabled" ) ) {
1018                const submenu_offset = $toggle_bar.offset();
1019                const target_offset = $force_width_el.offset();
1020
1021                $menu.css({
1022                    width: $force_width_el.outerWidth(),
1023                    left: (target_offset.left - submenu_offset.left) + "px"
1024                });
1025            }
1026        };
1027
1028        plugin.doConsoleChecks = function() {
1029            if (plugin.settings.mobile_force_width !== "false" && ! $(plugin.settings.mobile_force_width).length && ( plugin.settings.effect_mobile === "slide" || plugin.settings.effect_mobile === "disabled" ) ) {
1030                console.warn('Max Mega Menu #' + $wrap.attr('id') + ': Mobile Force Width element (' + plugin.settings.mobile_force_width + ') not found');
1031            }
1032
1033            const cssWidthRegex = /^((\d+(\.\d+)?(px|%|em|rem|vw|vh|ch|ex|cm|mm|in|pt|pc))|auto)$/i;
1034
1035            if (plugin.settings.panel_width !== undefined && ! cssWidthRegex.test(plugin.settings.panel_width) && ! $(plugin.settings.panel_width).length ) {
1036                console.warn('Max Mega Menu #' + $wrap.attr('id') + ': Panel Width (Outer) element (' + plugin.settings.panel_width + ') not found');
1037            }
1038
1039            if (plugin.settings.panel_inner_width !== undefined && ! cssWidthRegex.test(plugin.settings.panel_inner_width) && ! $(plugin.settings.panel_inner_width).length ) {
1040                console.warn('Max Mega Menu #' + $wrap.attr('id') + ': Panel Width (Inner) element (' + plugin.settings.panel_inner_width + ') not found');
1041            }
1042        };
1043
1044        plugin.init = function() {
1045            $menu.triggerHandler("before_mega_menu_init");
1046            plugin.settings = $.extend({}, defaults, options);
1047
1048            if (window.console) {
1049                plugin.doConsoleChecks();
1050            }
1051
1052            $menu.removeClass("mega-no-js");
1053
1054            plugin.initToggleBar();
1055            
1056            if (plugin.settings.unbind_events === "true") {
1057                plugin.unbindAllEvents();
1058            }
1059
1060            if ( document.readyState === 'complete' ) {
1061                plugin.calculateDynamicSubmenuWidths($("> li.mega-menu-megamenu > a.mega-menu-link", $menu));
1062            } else {
1063                $(window).on("load", function() {
1064                    plugin.calculateDynamicSubmenuWidths($("> li.mega-menu-megamenu > a.mega-menu-link", $menu));
1065                });
1066            }
1067
1068            if ( plugin.isDesktopView() ) {
1069                plugin.initDesktop();
1070            } else {
1071                plugin.initMobile();
1072            }
1073
1074            $(window).on("resize", function() {
1075                plugin.checkWidth();
1076            });
1077
1078            $menu.triggerHandler("after_mega_menu_init");
1079        };
1080
1081        plugin.init();
1082    };
1083
1084    $.fn.maxmegamenu = function(options) {
1085        return this.each(function() {
1086            if (undefined === $(this).data("maxmegamenu")) {
1087                const plugin = new $.maxmegamenu(this, options);
1088                $(this).data("maxmegamenu", plugin);
1089            }
1090        });
1091    };
1092
1093    $(function() {
1094        $(".max-mega-menu").maxmegamenu();
1095    });
1096}( jQuery ));

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.