By default on mouseenter event menu get open but I would like to change the event to click so for that I've override following file
lib/web/mage/menu.js
and made the following change for _toggleDesktopMode function but it's not working.
_toggleDesktopMode: function () {
var categoryParent, html;
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);
}
}
}
},
'click .ui-menu-item': function (event) {
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'
});
categoryParent = this.element.find('.all-category');
html = $('html');
categoryParent.remove();
if (html.hasClass('nav-open')) {
html.removeClass('nav-open');
setTimeout(function () {
html.removeClass('nav-before-open');
}, 300);
}
}
Any suggestion what is wrong?
-
can anyone help?Kaushal Suthar– Kaushal Suthar2018年08月28日 13:02:10 +00:00Commented Aug 28, 2018 at 13:02
4 Answers 4
No need to override
lib/web/mage/menu.js
Just go to
app/design/frontent/YourVendor/YourTheme/Magento_Theme/templates/html/topmenu.phtml
Inside ul data-mage-init add
"mediaBreakpoint": "(max-width: 1824px)"
Code should look like below
<ul data-mage-init='{"menu":{"responsive":true, "expanded":true, "mediaBreakpoint": "(max-width: 1824px)", "position":{"my":"left top","at":"left bottom"}}}'>
By doing this menu.js will execute _toggleMobileMode() and in this mode, menu will open on click, not on hover.
-
ur given solution is working but while click on the menu it scrolls do you have any idea how to fixed ?Navin Bhudiya– Navin Bhudiya2019年05月16日 11:11:42 +00:00Commented May 16, 2019 at 11:11
-
Didn't work for me in Magento 2.3.4PauGNU– PauGNU2020年07月21日 13:15:34 +00:00Commented Jul 21, 2020 at 13:15
In my case (Magento 2.3.4), the solution from @Vince Verhoeven worked partially: I wanted the top level links to open the submenu in case there was one. So I had to detect whether there was a submenu or not to control this logic.
Just after:
'click .ui-menu-item:has(a)': function (event) {
I added a condition for the code to be executed:
if ($(event.target).siblings('.submenu').length || $(event.target).parent().siblings('.submenu').length) {
The final function looks like this:
/**
* @private
*/
_toggleDesktopMode: function () {
var categoryParent, html;
$(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) {
if ($(event.target).siblings('.submenu').length || $(event.target).parent().siblings('.submenu').length) {
event.preventDefault();
var target = $(event.target).closest('.ui-menu-item');
if (!this.mouseHandled && target.not('.ui-state-disabled').length) {
this.select(event);
// 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);
}
}
}
}
},
/**
* @param {jQuery.Event} event
*/
'click .ui-menu-item': function (event) {
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.
*/
});
categoryParent = this.element.find('.all-category');
html = $('html');
categoryParent.remove();
if (html.hasClass('nav-open')) {
html.removeClass('nav-open');
setTimeout(function () {
html.removeClass('nav-before-open');
}, this.options.hideDelay);
}
},
-
Thank you....Working Well.... :) +1Ronak Rathod– Ronak Rathod2021年03月31日 13:31:30 +00:00Commented Mar 31, 2021 at 13:31
-
I have the same requirement in 2.4.6. But it's not working. Do you have any idea what needs to be changed?Gaurav Agrawal– Gaurav Agrawal2023年08月15日 05:07:47 +00:00Commented Aug 15, 2023 at 5:07
You have to extend lib/web/mage/menu.js
on line 538 you see, you need to make click
'mouseenter .ui-menu-item':
and on line 579 you have to remove 'mouseleave .ui-menu': 'collapseAll'
example by extending menu.js
requirejs-config.js
var config = {
map: {
'*': {
"menu": "Magento_Theme/js/megaMenu"
},
},
megaMenu.js
define([
'jquery',
'mage/menu',
],
function ($) {
$.widget('my.megamenu', $.mage.menu, {
_init: function () {
this._super();
}, /**
* @private
*/
_toggleDesktopMode: function () {
var categoryParent, html;
$(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) {
console.log('mine');
event.preventDefault();
var target = $(event.target).closest('.ui-menu-item');
if (!this.mouseHandled && target.not('.ui-state-disabled').length) {
this.select(event);
// 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);
}
}
}
},
/**
* @param {jQuery.Event} event
*/
'click .ui-menu-item': function (event) {
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.
*/
});
categoryParent = this.element.find('.all-category');
html = $('html');
categoryParent.remove();
if (html.hasClass('nav-open')) {
html.removeClass('nav-open');
setTimeout(function () {
html.removeClass('nav-before-open');
}, this.options.hideDelay);
}
}
}
);
return $.my.megamenu;
});
-
This solution is no longer working on 2.4.4. Any other ideas?AboElnouR– AboElnouR2022年07月30日 23:00:56 +00:00Commented Jul 30, 2022 at 23:00
on 2.4.5
define(['jquery'], function ($) {
'use strict';
var menuMixin = {
// overriden method remove hover in desktop mode
// only open menu by clicking
_toggleDesktopMode: function () {
var categoryParent, html;
// remove mousemove listener
$(this.element).off('click mousedown mouseenter mouseleave mousemove');
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);
// Open submenu on click
if (target.has('.ui-menu').length) {
event.preventDefault();
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);
}
}
}
},
/**
* @param {jQuery.Event} event
*/
'click .ui-menu-item': function (event) {
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);
},
});
categoryParent = this.element.find('.all-category');
html = $('html');
categoryParent.remove();
if (html.hasClass('nav-open')) {
html.removeClass('nav-open');
setTimeout(function () {
html.removeClass('nav-before-open');
}, this.options.hideDelay);
}
}
};
return function (targetWidget) {
$.widget('mage.menu', targetWidget.menu, menuMixin);
return $.mage.menu;
};
});
-
please add details on your answerクジェー– クジェー2023年08月04日 08:23:55 +00:00Commented Aug 4, 2023 at 8:23