357 lines
11 KiB
JavaScript
357 lines
11 KiB
JavaScript
/* Cleaning this file properly is not neecessary, since it's an outdated library
|
|
* and will be replaced soon by a Vue component.
|
|
*/
|
|
|
|
import browser from 'browser';
|
|
import dom from 'dom';
|
|
import 'css!./navdrawer';
|
|
import 'scrollStyles';
|
|
|
|
export default function (options) {
|
|
function getTouches(e) {
|
|
return e.changedTouches || e.targetTouches || e.touches;
|
|
}
|
|
|
|
function onMenuTouchStart(e) {
|
|
options.target.classList.remove('transition');
|
|
var touches = getTouches(e);
|
|
var touch = touches[0] || {};
|
|
menuTouchStartX = touch.clientX;
|
|
menuTouchStartY = touch.clientY;
|
|
menuTouchStartTime = new Date().getTime();
|
|
}
|
|
|
|
function setVelocity(deltaX) {
|
|
var time = new Date().getTime() - (menuTouchStartTime || 0);
|
|
velocity = Math.abs(deltaX) / time;
|
|
}
|
|
|
|
function onMenuTouchMove(e) {
|
|
var isOpen = self.visible;
|
|
var touches = getTouches(e);
|
|
var touch = touches[0] || {};
|
|
var endX = touch.clientX || 0;
|
|
var endY = touch.clientY || 0;
|
|
var deltaX = endX - (menuTouchStartX || 0);
|
|
var deltaY = endY - (menuTouchStartY || 0);
|
|
setVelocity(deltaX);
|
|
|
|
if (isOpen && dragMode !== 1 && deltaX > 0) {
|
|
dragMode = 2;
|
|
}
|
|
|
|
if (dragMode === 0 && (!isOpen || Math.abs(deltaX) >= 10) && Math.abs(deltaY) < 5) {
|
|
dragMode = 1;
|
|
scrollContainer.addEventListener('scroll', disableEvent);
|
|
self.showMask();
|
|
} else if (dragMode === 0 && Math.abs(deltaY) >= 5) {
|
|
dragMode = 2;
|
|
}
|
|
|
|
if (dragMode === 1) {
|
|
newPos = currentPos + deltaX;
|
|
self.changeMenuPos();
|
|
}
|
|
}
|
|
|
|
function onMenuTouchEnd(e) {
|
|
options.target.classList.add('transition');
|
|
scrollContainer.removeEventListener('scroll', disableEvent);
|
|
dragMode = 0;
|
|
var touches = getTouches(e);
|
|
var touch = touches[0] || {};
|
|
var endX = touch.clientX || 0;
|
|
var endY = touch.clientY || 0;
|
|
var deltaX = endX - (menuTouchStartX || 0);
|
|
var deltaY = endY - (menuTouchStartY || 0);
|
|
currentPos = deltaX;
|
|
self.checkMenuState(deltaX, deltaY);
|
|
}
|
|
|
|
function onEdgeTouchStart(e) {
|
|
if (isPeeking) {
|
|
onMenuTouchMove(e);
|
|
} else {
|
|
if (((getTouches(e)[0] || {}).clientX || 0) <= options.handleSize) {
|
|
isPeeking = true;
|
|
|
|
if (e.type === 'touchstart') {
|
|
dom.removeEventListener(edgeContainer, 'touchmove', onEdgeTouchMove, {});
|
|
dom.addEventListener(edgeContainer, 'touchmove', onEdgeTouchMove, {});
|
|
}
|
|
|
|
onMenuTouchStart(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
function onEdgeTouchMove(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
onEdgeTouchStart(e);
|
|
}
|
|
|
|
function onEdgeTouchEnd(e) {
|
|
if (isPeeking) {
|
|
isPeeking = false;
|
|
dom.removeEventListener(edgeContainer, 'touchmove', onEdgeTouchMove, {});
|
|
onMenuTouchEnd(e);
|
|
}
|
|
}
|
|
|
|
function disableEvent(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
|
|
function onBackgroundTouchStart(e) {
|
|
var touches = getTouches(e);
|
|
var touch = touches[0] || {};
|
|
backgroundTouchStartX = touch.clientX;
|
|
backgroundTouchStartTime = new Date().getTime();
|
|
}
|
|
|
|
function onBackgroundTouchMove(e) {
|
|
var touches = getTouches(e);
|
|
var touch = touches[0] || {};
|
|
var endX = touch.clientX || 0;
|
|
|
|
if (endX <= options.width && self.isVisible) {
|
|
countStart++;
|
|
var deltaX = endX - (backgroundTouchStartX || 0);
|
|
|
|
if (countStart == 1) {
|
|
startPoint = deltaX;
|
|
}
|
|
if (deltaX < 0 && dragMode !== 2) {
|
|
dragMode = 1;
|
|
newPos = deltaX - startPoint + options.width;
|
|
self.changeMenuPos();
|
|
var time = new Date().getTime() - (backgroundTouchStartTime || 0);
|
|
velocity = Math.abs(deltaX) / time;
|
|
}
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
|
|
function onBackgroundTouchEnd(e) {
|
|
var touches = getTouches(e);
|
|
var touch = touches[0] || {};
|
|
var endX = touch.clientX || 0;
|
|
var deltaX = endX - (backgroundTouchStartX || 0);
|
|
self.checkMenuState(deltaX);
|
|
countStart = 0;
|
|
}
|
|
|
|
function onMaskTransitionEnd() {
|
|
var classList = mask.classList;
|
|
|
|
if (!classList.contains('backdrop')) {
|
|
classList.add('hide');
|
|
}
|
|
}
|
|
|
|
var self;
|
|
var defaults;
|
|
var mask;
|
|
var newPos = 0;
|
|
var currentPos = 0;
|
|
var startPoint = 0;
|
|
var countStart = 0;
|
|
var velocity = 0;
|
|
options.target.classList.add('transition');
|
|
var dragMode = 0;
|
|
var scrollContainer = options.target.querySelector('.mainDrawer-scrollContainer');
|
|
scrollContainer.classList.add('scrollY');
|
|
|
|
var TouchMenuLA = function () {
|
|
self = this;
|
|
defaults = {
|
|
width: 260,
|
|
handleSize: 10,
|
|
disableMask: false,
|
|
maxMaskOpacity: 0.5
|
|
};
|
|
this.isVisible = false;
|
|
this.initialize();
|
|
};
|
|
|
|
TouchMenuLA.prototype.initElements = function () {
|
|
options.target.classList.add('touch-menu-la');
|
|
options.target.style.width = options.width + 'px';
|
|
options.target.style.left = -options.width + 'px';
|
|
|
|
if (!options.disableMask) {
|
|
mask = document.createElement('div');
|
|
mask.className = 'tmla-mask hide';
|
|
document.body.appendChild(mask);
|
|
dom.addEventListener(mask, dom.whichTransitionEvent(), onMaskTransitionEnd, {
|
|
passive: true
|
|
});
|
|
}
|
|
};
|
|
|
|
var menuTouchStartX;
|
|
var menuTouchStartY;
|
|
var menuTouchStartTime;
|
|
var edgeContainer = document.querySelector('.mainDrawerHandle');
|
|
var isPeeking = false;
|
|
|
|
TouchMenuLA.prototype.animateToPosition = function (pos) {
|
|
requestAnimationFrame(function () {
|
|
options.target.style.transform = pos ? 'translateX(' + pos + 'px)' : 'none';
|
|
});
|
|
};
|
|
|
|
TouchMenuLA.prototype.changeMenuPos = function () {
|
|
if (newPos <= options.width) {
|
|
this.animateToPosition(newPos);
|
|
}
|
|
};
|
|
|
|
TouchMenuLA.prototype.clickMaskClose = function () {
|
|
mask.addEventListener('click', function () {
|
|
self.close();
|
|
});
|
|
};
|
|
|
|
TouchMenuLA.prototype.checkMenuState = function (deltaX, deltaY) {
|
|
if (velocity >= 0.4) {
|
|
if (deltaX >= 0 || Math.abs(deltaY || 0) >= 70) {
|
|
self.open();
|
|
} else {
|
|
self.close();
|
|
}
|
|
} else {
|
|
if (newPos >= 100) {
|
|
self.open();
|
|
} else {
|
|
if (newPos) {
|
|
self.close();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
TouchMenuLA.prototype.open = function () {
|
|
this.animateToPosition(options.width);
|
|
currentPos = options.width;
|
|
this.isVisible = true;
|
|
options.target.classList.add('drawer-open');
|
|
self.showMask();
|
|
self.invoke(options.onChange);
|
|
};
|
|
|
|
TouchMenuLA.prototype.close = function () {
|
|
this.animateToPosition(0);
|
|
currentPos = 0;
|
|
self.isVisible = false;
|
|
options.target.classList.remove('drawer-open');
|
|
self.hideMask();
|
|
self.invoke(options.onChange);
|
|
};
|
|
|
|
TouchMenuLA.prototype.toggle = function () {
|
|
if (self.isVisible) {
|
|
self.close();
|
|
} else {
|
|
self.open();
|
|
}
|
|
};
|
|
|
|
var backgroundTouchStartX;
|
|
var backgroundTouchStartTime;
|
|
|
|
TouchMenuLA.prototype.showMask = function () {
|
|
mask.classList.remove('hide');
|
|
mask.classList.add('backdrop');
|
|
};
|
|
|
|
TouchMenuLA.prototype.hideMask = function () {
|
|
mask.classList.add('hide');
|
|
mask.classList.remove('backdrop');
|
|
};
|
|
|
|
TouchMenuLA.prototype.invoke = function (fn) {
|
|
if (fn) {
|
|
fn.apply(self);
|
|
}
|
|
};
|
|
|
|
var _edgeSwipeEnabled;
|
|
|
|
TouchMenuLA.prototype.setEdgeSwipeEnabled = function (enabled) {
|
|
if (!options.disableEdgeSwipe) {
|
|
if (browser.touch) {
|
|
if (enabled) {
|
|
if (!_edgeSwipeEnabled) {
|
|
_edgeSwipeEnabled = true;
|
|
dom.addEventListener(edgeContainer, 'touchstart', onEdgeTouchStart, {
|
|
passive: true
|
|
});
|
|
dom.addEventListener(edgeContainer, 'touchend', onEdgeTouchEnd, {
|
|
passive: true
|
|
});
|
|
dom.addEventListener(edgeContainer, 'touchcancel', onEdgeTouchEnd, {
|
|
passive: true
|
|
});
|
|
}
|
|
} else {
|
|
if (_edgeSwipeEnabled) {
|
|
_edgeSwipeEnabled = false;
|
|
dom.removeEventListener(edgeContainer, 'touchstart', onEdgeTouchStart, {
|
|
passive: true
|
|
});
|
|
dom.removeEventListener(edgeContainer, 'touchend', onEdgeTouchEnd, {
|
|
passive: true
|
|
});
|
|
dom.removeEventListener(edgeContainer, 'touchcancel', onEdgeTouchEnd, {
|
|
passive: true
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
TouchMenuLA.prototype.initialize = function () {
|
|
options = Object.assign(defaults, options || {});
|
|
|
|
if (browser.edge) {
|
|
options.disableEdgeSwipe = true;
|
|
}
|
|
|
|
self.initElements();
|
|
|
|
if (browser.touch) {
|
|
dom.addEventListener(options.target, 'touchstart', onMenuTouchStart, {
|
|
passive: true
|
|
});
|
|
dom.addEventListener(options.target, 'touchmove', onMenuTouchMove, {
|
|
passive: true
|
|
});
|
|
dom.addEventListener(options.target, 'touchend', onMenuTouchEnd, {
|
|
passive: true
|
|
});
|
|
dom.addEventListener(options.target, 'touchcancel', onMenuTouchEnd, {
|
|
passive: true
|
|
});
|
|
dom.addEventListener(mask, 'touchstart', onBackgroundTouchStart, {
|
|
passive: true
|
|
});
|
|
dom.addEventListener(mask, 'touchmove', onBackgroundTouchMove, {});
|
|
dom.addEventListener(mask, 'touchend', onBackgroundTouchEnd, {
|
|
passive: true
|
|
});
|
|
dom.addEventListener(mask, 'touchcancel', onBackgroundTouchEnd, {
|
|
passive: true
|
|
});
|
|
}
|
|
|
|
self.clickMaskClose();
|
|
};
|
|
|
|
return new TouchMenuLA();
|
|
}
|