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?