Magento Asked by Kaushal Suthar on November 8, 2021
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?
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);
}
},
Answered by PauGNU on November 8, 2021
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;
});
Answered by Vince Verhoeven on November 8, 2021
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.
Answered by Mathew Lawrence on November 8, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP