mmenu-js
Version:
The best javascript plugin for app look-alike on- and off-canvas menus with sliding submenus for your website and webapp.
109 lines (91 loc) • 3.87 kB
text/typescript
import Mmenu from './../oncanvas/mmenu.oncanvas';
import OPTIONS from './options';
import * as DOM from '../../_modules/dom';
import * as support from '../../_modules/support';
import { extend, touchDirection } from '../../_modules/helpers';
export default function (this: Mmenu) {
// The scrollBugFix add-on fixes a scrolling bug
// 1) on touch devices
// 2) in an off-canvas menu
if (
!support.touch || // 1
!this.opts.offCanvas.use // 2
) {
return;
}
this.opts.scrollBugFix = this.opts.scrollBugFix || {};
// Extend options.
const options = extend(this.opts.scrollBugFix, OPTIONS);
if (!options.fix) {
return;
}
/** The touch-direction instance. */
const touchDir = touchDirection(this.node.menu);
// Prevent the page from scrolling when scrolling in the menu.
this.node.menu.addEventListener('scroll', evnt => {
evnt.preventDefault();
evnt.stopPropagation();
}, {
// Make sure to tell the browser the event will be prevented.
passive: false,
});
// Prevent the page from scrolling when dragging in the menu.
this.node.menu.addEventListener(
'touchmove',
evnt => {
let wrapper = (evnt.target as HTMLElement).closest(
'.mm-panel, .mm-iconbar__top, .mm-iconbar__bottom'
) as HTMLElement;
if (wrapper && wrapper.closest('.mm-listitem--vertical')) {
wrapper = DOM.parents(wrapper, '.mm-panel').pop();
}
if (wrapper) {
// When dragging a non-scrollable panel/iconbar,
// we can simply stopPropagation.
if (wrapper.scrollHeight === wrapper.offsetHeight) {
evnt.stopPropagation();
}
// When dragging a scrollable panel/iconbar,
// that is fully scrolled up (or down).
// It will not trigger the scroll event when dragging down (or up) (because you can't scroll up (or down)),
// so we need to match the dragging direction with the scroll position before preventDefault and stopPropagation,
// otherwise the panel would not scroll at all in any direction.
else if (
// When scrolled up and dragging down
(wrapper.scrollTop == 0 && touchDir.get() == 'down') ||
// When scrolled down and dragging up
(wrapper.scrollHeight ==
wrapper.scrollTop + wrapper.offsetHeight &&
touchDir.get() == 'up')
) {
evnt.stopPropagation();
}
// When dragging anything other than a panel/iconbar.
} else {
evnt.stopPropagation();
}
},
{
// Make sure to tell the browser the event can be prevented.
passive: false,
}
);
// Some small additional improvements
// Scroll the current opened panel to the top when opening the menu.
this.bind('open:after', () => {
var panel = DOM.children(this.node.pnls, '.mm-panel--opened')[0];
if (panel) {
panel.scrollTop = 0;
}
});
// Fix issue after device rotation change.
window.addEventListener('orientationchange', (evnt) => {
var panel = DOM.children(this.node.pnls, '.mm-panel--opened')[0];
if (panel) {
panel.scrollTop = 0;
// Apparently, changing the overflow-scrolling property triggers some event :)
panel.style['-webkit-overflow-scrolling'] = 'auto';
panel.style['-webkit-overflow-scrolling'] = 'touch';
}
});
}