Menu Handler is a javascript tool that adds logic and functionality to side menus, dropdowns and popups while emphasizing on accessibility.
es6, no dependencies.
internet explorer not supported.
functionality added to the menus by the library:
- open
- close
- close on esc press
- close on blur
- close all menus on menu open
- close all submenus on submenu open
- close submenus on blur
- close submenus on mouseleave
- prevent body scroll when a menu is open
- accessiblity
- events
- pin menu to keep it open for specific breakpoints and hide at another breakpoint unless opened.
- mobile options
- replacing specific menu's functionality with custom functionality by passing custom function
- and more...
- init - init with array of menu objects
- css - add the following css
- menu container - required - element that holds nothing, but the inner container.
- menu inner container - required - element that holds all the menu elements.
- menu list - required - element that holds all the menu items.
- submenu toggle - required - element to trigger open / close of the submenu list.
- submenu list - required - element that holds the submenu items.
- submenu container - element that wraps the submenu list.
- html example - a complete example of a menu structure with submenus
- name - a unique menu name that will be used for the menu.
- container - required - menu container element that contains inner menu container.
- innerContainer - required - element that holds all menu elements.
- open - required - element that triggers opening of the menu.
- close - element that triggers menu closing of the menu.
- enterFocus - element to focus first when menu opens, will make any provided element focusable.
- exitFocus - element to focus after menu closes.
- pin - pin menu to keep it open at desktop media queries.
- loop - loop all elements inside the innerContainer using Tab key.
- preventBodyScroll - disables the ability to scroll the body.
- openDelay - sets delay in miliseconds before menu starts opening.
- closeDelay - sets delay in miliseconds before menu starts closing.
- debounce - sets debounce treshhold in miliseconds on menu liseteners.
- openOnMouseEnter - triggers opening of a menu by mouse enter.
- menuFunc - function to handle on your own of the specific menu.
- breakpoint - max width breakpoint to switch between mobile and desktop options.
- open - element that triggers opening of the menu at mobile breakpoint.
- close - element that triggers closing of the menu at mobile breakpoint.
- enterFocus - element to focus first when menu opens, will make any provided element focusable at mobile breakpoint.
- exitFocus - element to focus after menu closes at mobile breakpoint.
- pin - pin menu to keep it open at mobile media breakpoint.
- preventBodyScroll - disables the ability to scroll the body at mobile breakpoint.
- isEnabled - enables handling of submenus.
- openOnMouseEnter - triggers opening of a submenu on mouse enter.
- closeOnBlur - triggers closing of a submenu on blur.
- closeOnMouseLeave - triggers closing of a submenu on mouseleave.
- closeDelay - sets delay in miliseconds before submenu starts closing.
- closeSubmenusOnOpen - triggers closing of other submenus on opening of a submenu.
- menuFunc - function to handle submenus on your own the specific menu.
- closeOnBlur - triggers closing of a submenu on blur at mobile breakpoint.
- closeDelay - sets delay in miliseconds before submenu starts closing at mobile breakpoint.
- closeSubmenusOnOpen - triggers closing of other submenus on opening of a submenu at mobile breakpoint.
- beforeInit - triggered before the specific menu is initialized.
- afterInit - triggered after the specific menu is initialized.
- beforeOpen - triggered before the specific menu is opened.
- afterOpen - triggered after the specific menu finished transition and is opened.
- beforeClose - triggered before the specific menu is closed.
- afterClose - triggered after the specific menu finished transition and is closed.
- beforePinOpen - triggered before the specific menu is pinned.
- afterPinOpen - triggered after the specific menu finished transition and is pinned.
- beforePinClose - triggered before the specific menu is unpinned.
- afterPinClose - triggered after the specific menu finished transition and is unpinned.
- beforeOpen - triggered before the specific submenu is opened.
- afterOpen - triggered after the specific submenu finished transition and is opened
- beforeClose - triggered before the specific submenu is closed.
- afterClose - triggered after the specific submenu finished transition and is closed
- activeOpen - the active element which triggers opening of the menu
- activeClose - the active element which triggers closing of the menu
- isOpen - Shows the status of the menu at run time
- isPinned - Shows if menu is pinned at run time
- isMobile - Shows the status of menu mobile state at run time
- isOpen - Shows the status of the submenu at run time
init with array of menu objects.
❗ note: it is possible to initialize menuHandler in several files. it is not creating new instance, but merging the menus in one instance to work with each others.
const menus = [
{
elements: {
open: "#menu-open",
close: "#menu-close",
container: "#menu-container",
innerContainer: "#menu-inner-container"
},
loop: true
}
];
menuHandler.init(menus);add the following css:
.mh-hidden {
display: none !important;
}❗ note: the aim of the library is purely handle the functionality of side menus, popups and dropdowns. the html and css aspects differ from project to project, so it is something you should do on your side. we give a guideline on a solid html structure that is the minimum required for a valid sidemenu, dropdown and popup to be implemented.
element that holds nothing, but the inner container.
required
<div id="menu-container">
<div class="mh-hidden" id="menu-inner-container">
...
</div>
</div>element that holds all the menu elements.
required
❗ note: inner container should have class mh-hidden.
<div id="menu-container">
<div class="mh-hidden" id="menu-inner-container">
...
</div>
</div>element that holds all the menu items.
required
❗ note: menu list should have attribute data-mh-menu-list="true".
<div id="menu-container">
<div class="mh-hidden" id="menu-inner-container">
<ul data-mh-menu-list="true">
...
</ul>
<ul data-mh-menu-list="true">
...
</ul>
</div>
</div>element to trigger open / close of the submenu list
required
❗ note: submenu toggle button element should have data attribute data-mh-submenu-toggle and it's value the submenu name ( a unique identifier ).
<button data-mh-submenu-toggle="submenu-a">
...
</button>element that holds the submenu items
required
❗ note : submenu list element should have data attribue data-mh-submenu-list and it's value the submenu name ( same as the submenu toggle identifier ).
❗ note : submenu list element should have class mh-hidden.
<ul class="mh-hidden" data-mh-submenu-list="submenu-a">
...
</ul>element that wraps the submenu list.
optional
❗ note : submenu container should have data attribute data-mh-submenu-container and it's value the submenu name ( same as the submenu toggle identifier ).
❗ note: if present ,submenu container will get mh-open class when submenu is opened.
<div data-mh-submenu-container="submenu-a">
...
</div>❗ submenu container is handy for situations when you want to do an opening and closing animation for the submenu.
scss example:
[data-mh-submenu-container] {
height: auto;
max-height: 0;
overflow: hidden;
transition: 0.3s max-height ease-in-out;
&.mh-open {
max-height: 1000px; // just some high number that the submenu height will never get to it.
}
}complete example of a menu structure with submenus
<div id="menu-container" aria-hidden="true">
<div class="mh-hidden" id="menu-inner-container">
<nav id="menu-enter-focus">
<ul class="menu" data-mh-menu-list="true">
<li>
<button data-mh-submenu-toggle="submenu-a" aria-expanded="false" aria-controls="mh-submenu-submenu-a" title="">
submenu-a trigger button
</button>
<div data-mh-submenu-container="submenu-a">
<ul id="mh-submenu-submenu-a" class="mh-hidden" data-mh-submenu-list="submenu-a" aria-hidden="true">
<li>
<button data-mh-submenu-toggle="submenu-a-1" aria-expanded="false" aria-controls="mh-submenu-submenu-a-1" title="">
submenu-a-1 trigger button
</button>
<div data-mh-submenu-container="submenu-a-1">
<ul id="mh-submenu-submenu-a-1" class="mh-hidden" data-mh-submenu-list="submenu-a-1" aria-hidden="true">
...
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</nav>
<button id="menu-close" aria-controls="menu-container" aria-expanded="false" title="">
menu toggle button
</button>
</div>
</div>a unique menu name that will be used for the menu
default: randomly generated name
type: string
menu container element that contains inner menu container. see example
required
type: css selector
❗ note: holds nothing, but the inner container.
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: ...,
open: ...
}
}
];
menuHandler.init(menus);element that holds all menu elements. see example
required
type: css selector
❗ note: gets class mh-hidden when menu is closed
const menus = [
{
elements: {
container: ...,
innerContainer: "#menu-inner-container",
open: ...
}
}
];
menuHandler.init(menus);element that triggers opening of the menu
required
type: css selector
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: "#menu-toggle-open"
}
}
];
menuHandler.init(menus);element that triggers closing of the menu
type: css selector
default: element.close
❗ note: required ,if loop is set to true for accessibility reasons.
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: ...,
close: "#menu-toggle-close"
}
}
];
menuHandler.init(menus);element to focus first when menu opens, will make any provided element focusable
type: css selector
default: first focusable element
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: ...,
enterFocus: "#menu-enter-focus"
}
}
];
menuHandler.init(menus);element to focus after menu closes
type: css selector
default: elements.open
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: ...,
exitFocus: "#menu-exit-focus"
}
}
];
menuHandler.init(menus);pin menu to keep it open at desktop media queries. a
type: css selector
default: false
❗ note: adds class mh-pinned to elements.container when menu is pinned.
❗ note: if pin is set to true ,then the following functionalities of the menu are disabled: open, close.
❗ note: adds class mh-hidden to menu toggle buttons (elements.open,elements.close,elements.mobile.open,elements.mobile.close) when menu is pinned.
❗ note: blur and ESC press events won't close a pinned menu, but will close all submenus.
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: ...,
},
pin: true
}
];
menuHandler.init(menus);loop all elements inside the elements.innerContainer using Tab key for accessibility purposes until a elements.close or ESC key are pressed
type: boolean
default: false
❗ note: if loop is true, elements.close has is required, because a person using tabs will never escape out of the menu and make sure you put the elements.close element inside the elements.innerContainer
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open",
close: "#menu-toggle-close"
},
loop: true
}
];
menuHandler.init(menus);disables the ability to scroll the body.
type: boolean
default: true
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open",
},
preventBodyScroll: false, // to disable the feature
}
];
menuHandler.init(menus);sets delay in miliseconds before menu starts opening
type: integer
default: 0
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
openDelay: 2000
}
];
menuHandler.init(menus);sets delay in miliseconds before menu starts closing
type: integer
default: 0
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
closeDelay: 1000
}
];
menuHandler.init(menus);sets debounce treshhold in miliseconds on menu liseteners.
type: integer
default: 20
❗ note: to disable debounce set value to 0 (not recommended).
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
debounce: 30
}
];
menuHandler.init(menus);triggers opening of a menu on mouse enter
type: boolean
default: false
❗ note: disabled ,if screen viewport is less ,than mobile.breakpoint.
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
openOnMouseEnter: true
}
];
menuHandler.init(menus);function to handle on your own of the specific menu
type: function
arguments:
menutype:objectetype:event❗ note: on open, close events related to the menu will need to be included in the custom function in order for them to work which can be accessed from the menu object
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
menuFunc: function(menu, e) {
console.log(menu);
}
}
];
menuHandler.init(menus);❗ note: default code
function(menu, e) {
if (menu.isOpen) {
menu.open.setAttribute('aria-expanded', true);
if (menu.mobile.open) menu.mobile.open.setAttribute('aria-expanded', true);
menu.container.setAttribute('aria-hidden', false);
menu.innerContainer.classList.remove('mh-hidden');
menu.activeEnterFocus.focus();
} else {
menu.open.setAttribute('aria-expanded', false);
if (menu.mobile.open) menu.mobile.open.setAttribute('aria-expanded', false);
menu.container.setAttribute('aria-hidden', true);
menu.innerContainer.classList.add('mh-hidden');
}
}max width breakpoint to switch between mobile and desktop options.
type: string
default: 667px
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
mobile: {
breakpoint: "991px"
}
}
];
menuHandler.init(menus);element that triggers opening of the menu at mobile.breakpoint.
type: css selector
default: elements.open
❗ note: if pin is set to true at desktop media queries ,then you don't need to pass this selector ,just pass open.
❗ note: if both mobile.elements.open and open are passed ,then mobile.elements.open is the one that will trigger open in mobile.breakpoint and open in larger media queries.
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: ...,
},
mobile: {
elements: {
open: "#menu-mobile-toggle-open"
}
}
}
];
menuHandler.init(menus);element that triggers closing of the menu at mobile.breakpoint.
type: css selector
default: elements.close
❗ note: close is required, if using mobile.close.
❗ note: if both mobile.elements.close and close are passed ,then mobile.elements.close is the one that will trigger close in mobile.breakpoint and close in larger media queries.
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: ...,
close: ...,
},
mobile: {
elements: {
close: "#menu-mobile-toggle-close"
}
}
}
];
menuHandler.init(menus);element to focus first when menu opens, will make any provided element focusable at mobile.breakpoint.
type: css selector
default: elements.enterFocus
❗ note: if both mobile.elements.enterFocus and enterFocus are passed ,then mobile.elements.enterFocus is the one that will get focused in mobile.breakpoint and close in larger media queries.
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: ...,
},
mobile: {
elements: {
enterFocus: "#menu-enter-focus"
}
}
}
];
menuHandler.init(menus);element to focus after menu closes at mobile.breakpoint.
type: css selector
default: elements.exitFocus
❗ note: if both mobile.elements.exitFocus and exitFocus are passed ,then mobile.elements.exitFocus is the one that will get focused in mobile.breakpoint and close in larger media queries.
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: ...,
},
mobile: {
elements: {
exitFocus: "#menu-exit-focus"
}
}
}
];
menuHandler.init(menus);pin menu to keep it open at mobile.breakpoint.
type: css selector
default: false
❗ note: adds class mh-pinned to elements.container when menu is pinned.
❗ note: if mobile.pin is set to true ,then the following functionalities of the menu are disabled: open, close.
❗ note: adds class mh-hidden to menu toggle buttons (elements.open,elements.close,elements.mobile.open,elements.mobile.close) when menu is pinned.
❗ note: blur and ESC press events won't close a pinned menu, but will close all submenus.
const menus = [
{
elements: {
container: ...,
innerContainer: ...,
open: ...,
},
mobile: {
pin: true,
}
}
];
menuHandler.init(menus);disables the ability to scroll the body at mobile.breakpoint.
type: boolean
default: true
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open",
},
mobile: {
preventBodyScroll: false, // to disable the feature
},
}
];
menuHandler.init(menus);enables handling of submenus
type: boolean
default: true
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
isEnabled: false // to disable submenus
}
}
];
menuHandler.init(menus);triggers opening of a submenu on mouse enter
type: boolean
default: false
❗ note: disabled at mobile viewport (if screen viewport is less ,than mobile.breakpoint).
❗ note: to disable openOnMouseEnter of a specific submenu ,just add data-mh-mouseenter-disabled="true" attribute to the submenu toggle.
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
openOnMouseEnter: true
}
}
];
menuHandler.init(menus);triggers closing of a submenu on blur.
type: boolean
default: true
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
closeOnBlur: false, // to disable
}
}
];
menuHandler.init(menus);triggers closing of a submenu on mouseleave of the submenu toggle button, submenu container or submenu list.
type: boolean
default: false
❗ note: disabled at mobile viewport (if screen viewport is less ,than mobile.breakpoint).
❗ note: to disable closeOnMouseLeave of a specific submenu ,just add data-mh-mouseleave-disabled="true" attribute to the submenu toggle.
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
openOnMouseEnter: true, // suggested to use it in par with closeOnMouseLeave for a good user experience.
closeOnMouseLeave: true,
}
}
];
menuHandler.init(menus);sets delay in miliseconds before submenu starts closing.
type: integer
default: 0
❗ note: if used with submenuOptions.closeOnMouseLeave it will give a timeout window for the user to return back with the pointer into the toggle button, submenu container or submenu list and it will cancel the closing action.
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
openOnMouseEnter: true, // suggested to use it in par with closeOnMouseLeave for a good user experience.
closeOnMouseLeave: true,
closeDelay: 700,
}
}
];
menuHandler.init(menus);triggers closing of other submenus on opening of a submenu.
type: boolean
default: true
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
closeSubmenusOnOpen: false, // to keep submenus open
}
}
];
menuHandler.init(menus);function to handle submenus on your own the specific menu
type: function
arguments:
menutype:object
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
menuFunc: function(menu, e) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);❗ note: default code
function(menu, submenu, e) {
if (submenu.toggle.classList.contains('mh-open')) {
submenu.list.classList.remove('mh-hidden');
submenu.list.setAttribute('aria-hidden', false);
submenu.toggle.setAttribute('aria-expanded', true);
if (submenu.container) {
submenu.container.classList.add('mh-open');
} else {
submenu.list.classList.add('mh-open');
}
} else {
submenu.list.classList.add('mh-hidden');
submenu.list.setAttribute('aria-hidden', true);
submenu.toggle.setAttribute('aria-expanded', false);
if (submenu.container) {
submenu.container.classList.remove('mh-open');
} else {
submenu.list.classList.remove('mh-open');
}
}
}triggers closing of a submenu on blur at mobile mobile.breakpoint.
type: boolean
default: true
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open",
},
submenuOptions: {
mobile: {
closeOnBlur: false, // to disable
}
}
}
];
menuHandler.init(menus);sets delay in miliseconds before submenu starts closing at mobile mobile.breakpoint.
type: integer
default: 0
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
openOnMouseEnter: true, // suggested to use it in par with closeOnMouseLeave for a good user experience.
closeOnMouseLeave: true,
mobile: {
closeDelay: 700,
}
}
}
];
menuHandler.init(menus);triggers closing of other submenus on opening of a submenu at mobile mobile.breakpoint.
type: boolean
default: true
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
mobile: {
closeSubmenusOnOpen: false, // to keep submenus open
}
}
}
];
menuHandler.init(menus);triggered before the specific menu is initialized
type: function
arguments:
menutype:object
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
beforeInit: function(menu) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);triggered after the specific menu is initialized
type: function
arguments:
menutype:object
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
afterInit: function(menu) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);triggered before the specific menu is opened
type: function
arguments:
menutype:objectetype:event
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
beforeOpen: function(menu, e) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);triggered after the specific menu finished transition and is opened
type: function
arguments:
menutype:objectetype:event
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
afterOpen: function(menu, e) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);triggered before the specific menu is closed
type: function
arguments:
menutype:objectetype:event
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
beforeClose: function(menu, e) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);triggered after the specific menu finished transition and is closed
type: function
arguments:
menutype:objectetype:event
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
afterClose: function(menu, e) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);triggered before the specific menu is pinned
type: function
arguments:
menutype:object
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
beforePinOpen: function(menu) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);triggered after the specific menu finished transition and is pinned
type: function
arguments:
menutype:object
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
afterPinOpen: function(menu) {
console.log(menu);
}
}
}
];
menuHandler.init(menus); triggered before the specific menu is unpinned.
type: function
arguments:
menutype:object
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
beforePinClose: function(menu) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);triggered after the specific menu is finished transition and is unpinned.
type: function
arguments:
menutype:object
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
on: {
afterPinClose: function(menu) {
console.log(menu);
}
}
}
];
menuHandler.init(menus);triggered before the specific submenu is opened
type: function
arguments:
menutype:objectsubmenutype:objectetype:event
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
on: {
beforeOpen: function(menu, submenu, e) {
console.log(menu);
}
}
}
}
];
menuHandler.init(menus);triggered after the specific submenu finished transition and is opened
type: function
arguments:
menutype:objectsubmenutype:objectetype:event
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
on: {
afterOpen: function(menu, submenu, e) {
console.log(menu);
}
}
}
}
];
menuHandler.init(menus);triggered before the specific submenu is closed
type: function
arguments:
menutype:objectsubmenutype:objectetype:event
❗ note: e is null when the closing action was on the parent.
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
on: {
beforeClose: function(menu, submenu, e) {
console.log(menu);
}
}
}
}
];
menuHandler.init(menus);triggered after the specific submenu finished transition and is closed
type: function
arguments:
menutype:objectsubmenutype:objectetype:event
❗ note: e is null when the closing action was on the parent.
const menus = [
{
elements: {
container: "#menu-container",
innerContainer: "#menu-inner-container",
open: "#menu-toggle-open"
},
submenuOptions: {
on: {
afterClose: function(menu, submenu, e) {
console.log(menu);
}
}
}
}
];
menuHandler.init(menus);important menu parameters accessible via menu object
the active element which triggers opening of the menu
type: html element
default: elements.open ,if mobile.open is not empty and mobile.breakpoint query returns true ,then default is mobile.open.
❗ note: use this ,if you need it in the custom function you pass. don't use elements.open or mobile.elements.open
the active element which triggers closing of the menu
type: html element
default: elements.close ,if mobile.elements.close is not empty and mobile.breakpoint query returns true ,then default is mobile.elements.close.
❗ note: use this ,if you need it in the custom function you pass. don't use elements.close or mobile.elements.close
Shows the status of a menu at run time
type: boolean
default: false
❗ note: when menu isOpened a class mh-<<menu name>>-open is added to the body.
Shows if menu is pinned at run time
type: boolean
default: false
❗ note: when menu isPinned a class mh-pinned is added to elements.container.
❗ note: when menu isPinned a class class mh-hidden is added to menu toggle buttons (elements.open,elements.close,elements.mobile.open,elements.mobile.close).
Shows the status of menu mobile state at run time.
type: boolean
❗ note: affected by mobile.breakpoint and viewport width.
Shows the status of a submenu at run time
type: boolean
default: false
❗ note: when submenu isOpen a class mh-open is added to data-mh-submenu-toggle and data-mh-submenu-list.
❗ note: if data-mh-submenu-container is being used to contain the data-mh-submenu-list ,then data-mh-submenu-container will have mh-open instead of data-mh-submenu-list.