Skip to content

Magento 2 open top categories menu on click instead of hover not working on 2.4.4

I’ve developed a solution to make the top categories menu open ‘on click’ not ‘hover’, and it worked fine on Magento 2.3.4.

And this is my working solution.

My/Theme/view/frontend/requirejs-config.js content:

var config = {
    map: {
        '*': {
            "menu": "My_Theme/js/menu"
        }
    }
}

My/Theme/view/frontend/web/js/menu.js content:

define(
    ['jquery', 'mage/menu'],
    function ($) {
        $.widget('my.menu', $.mage.menu, {
            _init: function () {
                this._super();
            },

            /**
             * @private
             */
            _toggleDesktopMode: function () {
                var html, subMenus;

                $(this.element).off('click mousedown mouseenter mouseleave');
                this._on({

                    /**
                     * Prevent focus from sticking to links inside menu after clicking
                     * them (focus should always stay on UL during navigation).
                     */
                    'mousedown .ui-menu-item > a': function (event) {
                        event.preventDefault();
                    },

                    /**
                     * Prevent focus from sticking to links inside menu after clicking
                     * them (focus should always stay on UL during navigation).
                     */
                    'click .ui-state-disabled > a': function (event) {
                        event.preventDefault();
                    },

                    /**
                     * @param {jQuer.Event} event
                     */
                    'click .ui-menu-item:has(a)': function (event) {
                        var target = $(event.target).closest('.ui-menu-item');

                        if (!this.mouseHandled && target.not('.ui-state-disabled').length) {
                            this.select(event);

                            // Only set the mouseHandled flag if the event will bubble, see #9469.
                            if (!event.isPropagationStopped()) {
                                this.mouseHandled = true;
                            }

                            // Open submenu on click
                            if (target.has('.ui-menu').length) {
                                this.expand(event);
                            } else if (!this.element.is(':focus') &&
                                $(this.document[0].activeElement).closest('.ui-menu').length
                            ) {
                                // Redirect focus to the menu
                                this.element.trigger('focus', [true]);

                                // If the active item is on the top level, let it stay active.
                                // Otherwise, blur the active item since it is no longer visible.
                                if (this.active && this.active.parents('.ui-menu').length === 1) { //eslint-disable-line
                                    clearTimeout(this.timer);
                                }
                            }
                        }

                        subMenus = this.element.find('.level-top');
                        $.each(subMenus, $.proxy(function (index, item) {
                            var category = $(item).find('> a span').not('.ui-menu-icon').text(),
                                categoryUrl = $(item).find('> a').attr('href'),
                                menu = $(item).find('> .ui-menu');

                            this.categoryLink = $('<a>')
                                .attr('href', categoryUrl)
                                .text($.mage.__('All %1').replace('%1', category));

                            this.categoryParent = $('<li>')
                                .addClass('ui-menu-item all-category')
                                .html(this.categoryLink);

                            if (menu.find('.all-category').length === 0) {
                                menu.prepend(this.categoryParent);
                            }

                        }, this));
                    },

                    /**
                     * @param {jQuery.Event} event
                     */
                    'click .ui-menu-item.parent': function (event) {
                        var target = $(event.target).closest('.ui-menu-item');

                        if ($(target).hasClass('parent')) {
                            event.preventDefault();
                        }
                        var target = $(event.currentTarget),
                            submenu = this.options.menus,
                            ulElement,
                            ulElementWidth,
                            width,
                            targetPageX,
                            rightBound;

                        if (target.has(submenu)) {
                            ulElement = target.find(submenu);
                            ulElementWidth = ulElement.outerWidth(true);
                            width = target.outerWidth() * 2;
                            targetPageX = target.offset().left;
                            rightBound = $(window).width();

                            if (ulElementWidth + width + targetPageX > rightBound) {
                                ulElement.addClass('submenu-reverse');
                            }

                            if (targetPageX - ulElementWidth < 0) {
                                ulElement.removeClass('submenu-reverse');
                            }
                        }

                        // Remove ui-state-active class from siblings of the newly focused menu item
                        // to avoid a jump caused by adjacent elements both having a class with a border
                        target.siblings().children('.ui-state-active').removeClass('ui-state-active');
                        this.focus(event, target);
                    },

                    /**
                     * @param {jQuery.Event} event
                     */
                    'mouseenter .ui-menu-item': function (event) {
                        var target = $(event.target).closest('.ui-menu-item');

                        if ($(target).hasClass('level0')) {
                            return;
                        }
                        var target = $(event.currentTarget),
                            submenu = this.options.menus,
                            ulElement,
                            ulElementWidth,
                            width,
                            targetPageX,
                            rightBound;

                        if (target.has(submenu)) {
                            ulElement = target.find(submenu);
                            ulElementWidth = ulElement.outerWidth(true);
                            width = target.outerWidth() * 2;
                            targetPageX = target.offset().left;
                            rightBound = $(window).width();

                            if (ulElementWidth + width + targetPageX > rightBound) {
                                ulElement.addClass('submenu-reverse');
                            }

                            if (targetPageX - ulElementWidth < 0) {
                                ulElement.removeClass('submenu-reverse');
                            }
                        }

                        // Remove ui-state-active class from siblings of the newly focused menu item
                        // to avoid a jump caused by adjacent elements both having a class with a border
                        target.siblings().children('.ui-state-active').removeClass('ui-state-active');
                        this.focus(event, target);
                    },

                    /**
                     * @param {jQuery.Event} event
                     */
                    'mouseleave': function (event) {
                        this.collapseAll(event, true);
                    },

                    /**
                     * Mouse leave.
                     */
                    'mouseleave .ui-menu': 'collapseAll'
                });

                html = $('html');

                if (html.hasClass('nav-open')) {
                    html.removeClass('nav-open');
                    setTimeout(function () {
                        html.removeClass('nav-before-open');
                    }, this.options.hideDelay);
                }
            },
        })
    }
)

My changes on My/Theme/view/frontend/web/js/menu.js was the following:

1- I changed the line:
'mouseenter .ui-menu-item.parent': function (event) { to
'click .ui-menu-item.parent': function (event) {

2- I removed those two lines:
categoryParent = this.element.find('.all-category');
categoryParent.remove();

And everything was working perfectly.

Now and after upgrading to Magento 2.4.4 I found two issues:

1- My/Theme/view/frontend/requirejs-config.js not working at all.

2- even after I edited the core library file lib/web/mage/menu.js, my solution is not working.

Any help, please?