Add touch slideout menu for mobile

This commit is contained in:
Maxime Poulin 2016-06-11 22:16:17 -04:00
parent 828289af5a
commit 0eef5d9240
3 changed files with 137 additions and 15 deletions

View File

@ -303,13 +303,26 @@ button {
#viewport { #viewport {
height: 100%; height: 100%;
transition: all .4s; transition: transform 160ms, -webkit-transform 160ms;
-webkit-transform: translateZ(0); -webkit-transform: translateZ(0);
transform: translateZ(0); transform: translateZ(0);
-webkit-perspective: 1000; -webkit-perspective: 1000;
perspective: 1000; perspective: 1000;
} }
#viewport.menu-open {
-webkit-transform: translate3d(220px, 0, 0);
transform: translate3d(220px, 0, 0);
}
#viewport.menu-dragging {
transition: none !important;
}
#viewport.menu-open .messages {
pointer-events: none;
}
#viewport .lt, #viewport .lt,
#viewport .rt, #viewport .rt,
#chat button.menu { #chat button.menu {
@ -1595,11 +1608,6 @@ button {
margin-top: 60px !important; margin-top: 60px !important;
} }
#viewport.lt {
-webkit-transform: translate3d(220px, 0, 0);
transform: translate3d(220px, 0, 0);
}
#viewport.rt #chat .sidebar { #viewport.rt #chat .sidebar {
-webkit-transform: translate3d(-180px, 0, 0); -webkit-transform: translate3d(-180px, 0, 0);
transform: translate3d(-180px, 0, 0); transform: translate3d(-180px, 0, 0);
@ -1645,6 +1653,17 @@ button {
} }
} }
@media (min-width: 769px) {
#viewport {
-webkit-transform: none !important;
transform: none !important;
}
#viewport.menu-open {
transition: none;
}
}
@media (max-width: 479px) { @media (max-width: 479px) {
.container { .container {
margin: 40px 0 !important; margin: 40px 0 !important;

View File

@ -0,0 +1,99 @@
/**
* Simple slideout menu implementation.
*/
function slideoutMenu(viewport, menu) {
var touchStartPos = null;
var touchCurPos = null;
var touchStartTime = 0;
var menuWidth = parseFloat(window.getComputedStyle(menu).width);
var menuIsOpen = false;
var menuIsMoving = false;
function toggleMenu(state) {
menuIsOpen = state;
viewport.classList.toggle("menu-open", state);
}
function disableSlideout() {
viewport.removeEventListener("ontouchstart", onTouchStart);
}
function onTouchStart(e) {
if (e.touches.length !== 1) {
onTouchEnd();
return false;
}
var touch = e.touches.item(0);
viewport.classList.toggle("menu-dragging", true);
if ((!menuIsOpen && touch.screenX < 50) || (menuIsOpen && touch.screenX > menuWidth)) {
touchStartPos = touch;
touchCurPos = touch;
touchStartTime = Date.now();
viewport.addEventListener("touchmove", onTouchMove);
viewport.addEventListener("touchend", onTouchEnd);
}
}
function onTouchMove(e) {
var touch = touchCurPos = e.touches.item(0);
var setX = touch.screenX - touchStartPos.screenX;
if (Math.abs(setX > 30)) {
menuIsMoving = true;
}
if (!menuIsMoving && Math.abs(touch.screenY - touchStartPos.screenY) > 30) {
onTouchEnd();
return;
}
if (menuIsOpen) {
setX += menuWidth;
}
if (setX > menuWidth) {
setX = menuWidth;
} else if (setX < 0) {
setX = 0;
}
viewport.style.transform = "translate3d(" + setX + "px, 0, 0)";
if (menuIsMoving) {
e.preventDefault();
e.stopPropagation();
}
}
function onTouchEnd() {
var diff = touchCurPos.screenX - touchStartPos.screenX;
var absDiff = Math.abs(diff);
if (absDiff > menuWidth / 2 || Date.now() - touchStartTime < 180 && absDiff > 50) {
toggleMenu(diff > 0);
}
viewport.removeEventListener("touchmove", onTouchMove);
viewport.removeEventListener("touchend", onTouchEnd);
viewport.classList.toggle("menu-dragging", false);
viewport.style.transform = null;
touchStartPos = null;
touchCurPos = null;
touchStartTime = 0;
menuIsMoving = false;
}
viewport.addEventListener("touchstart", onTouchStart);
return {
disable: disableSlideout,
toggle: toggleMenu,
isOpen: function() {
return menuIsOpen;
}
};
}

View File

@ -542,19 +542,22 @@ $(function() {
}); });
var viewport = $("#viewport"); var viewport = $("#viewport");
var sidebarSlide = window.slideoutMenu(viewport[0], sidebar[0]);
var contextMenuContainer = $("#context-menu-container"); var contextMenuContainer = $("#context-menu-container");
var contextMenu = $("#context-menu"); var contextMenu = $("#context-menu");
viewport.on("click", ".lt, .rt", function(e) { $("#main").on("click", function(e) {
if ($(e.target).is(".lt")) {
sidebarSlide.toggle(!sidebarSlide.isOpen());
} else if (sidebarSlide.isOpen()) {
sidebarSlide.toggle(false);
}
});
viewport.on("click", ".rt", function(e) {
var self = $(this); var self = $(this);
viewport.toggleClass(self.attr("class")); viewport.toggleClass(self.attr("class"));
if (viewport.is(".lt, .rt")) { e.stopPropagation();
e.stopPropagation();
chat.find(".chat").one("click", function(e) {
e.stopPropagation();
viewport.removeClass("lt");
});
}
}); });
function positionContextMenu(that, e) { function positionContextMenu(that, e) {
@ -761,7 +764,8 @@ $(function() {
toggleNotificationMarkers(false); toggleNotificationMarkers(false);
} }
viewport.removeClass("lt"); sidebarSlide.toggle(false);
var lastActive = $("#windows > .active"); var lastActive = $("#windows > .active");
lastActive lastActive