Menu arrastavel simples

by Felype Rennan

HTML

<nav class="navegacao">
    <button class="xs-expandir">Menu</button>
    <button class="esquerda">&lt;&lt;</button>
    <div class="menu">
        <ul>
            <li>Item 1</li>
            <li>Item 2
                <ul class="abrir">
                    <li>Item 3</li>
                    <li>Item 3</li>
                    <li>Item 3</li>
                    <li>Item 3</li>
                    <li>Item 3</li>
                    <li>Item 3</li>
                </ul>
            </li>
            <li>Item 3</li>
            <li>Item 4</li>
            <li>Item 5</li>
            <li>Item 6</li>
            <li>Item 7</li>
            <li>Item 8</li>
            <li>Item 9</li>
        </ul>
    </div>
    <button class="direita">&gt;&gt;</button>
</nav>

SCSS

body {
    margin: 0; padding: 0;
}

$azul-facebook: #3a5795;

.menu {
	li > ul {
		background: $azul-facebook;
		position: absolute;
		z-index: 1001;
		display: none;
        padding: 0; margin: 0;
        top: 60px;
		> li {
            display: block;
            font-size: 18px;
            font-family: "Chuck Norris Sans", sans-serif;
            padding: 8px 16px;
            white-space: nowrap;
            cursor: pointer;
            &:hover {
                background: darken($azul-facebook, 12%);
                color:white;
            }
		}
	}
	li.abrir > ul {
		display: block;
	}
}

.navegacao {
    position: relative;
    height: 60px;
    background: $azul-facebook;
    > .xs-expandir { display: none; }
    > .menu {
	    overflow: visible;
	    color: white;
	    width: 100%;
	    position: fixed;
	    padding: 0 40px;    
		
	    > ul {
	        margin: 0; padding: 0;
	        list-style: none !important;
	        flex-wrap: nowrap;
	        display: block;
            left: 40px;
	        white-space: nowrap;
            position: absolute;
	        > li {
	            display: inline-block;
	            font-size: 22px;
	            font-family: "Chuck Norris Sans", sans-serif;
	            padding: 16px 16px;
	            white-space: nowrap;
	            cursor: pointer;
	            &:hover {
	                background: darken($azul-facebook, 12%);
	                color:white;
	            }
	        }
	    }
	}
	> .esquerda, > .direita {
        z-index: 1000;
        font-size: 22px;
        font-family: "Chuck Norris Sans", sans-serif;
        padding: 16px 8px;
        white-space: nowrap;
        cursor: pointer;
        position: absolute;
        color: white;
        display: block;
		border: none;
		outline: none;
        background: $azul-facebook;
        max-width: 36px; 
        top: 0;
        &:hover {
            background: darken($azul-facebook, 12%);
            color: white;
        }
    }
    > .esquerda {
       ...

JavaScript

var menuArraste = null;
var arrastando = false;

var scrollPerClick = 120; // em pixels;
var tempoScroll = 0.4;

var mouse = { x: 0, y: 0 };

$(".menu").find("li:has(ul)").click(function() {
    $(this).toggleClass("abrir");    
});

$(".navegacao > .xs-expandir").click(function(e) {
    $(this).siblings(".menu").toggleClass("abrir");    
});

$(document).mousemove(function(e) {
    if(menuArraste === null)
        return;
    if(!arrastando) {
        arrastando = true;
        mouse = {x: e.pageX, y: e.pageY};
        return;
    }
    var val = Number(menuArraste.css('left').replace("px","")) + (e.pageX - mouse.x );
    // o 40 Ă© uma margem pros botoes
    var offsetMax = (menuArraste.width()-menuArraste.parent().width()) + 40;
    if(val < -offsetMax) 
        val = -offsetMax;
    if(val > 40) 
        val = 40;
    menuArraste.css('left', val + "px");
    mouse = {x: e.pageX, y: e.pageY};
});

$(".direita").click(function(e) {
    var scrollCnt = 0;
    var timer = setInterval(
        function() {
            var delta = scrollPerClick / tempoScroll /10;
            scrollCnt += delta;
            var arraste = $(".menu > ul");
            var val = Number(arraste.css('left').replace("px",""));
            var offsetMax = (arraste.width()-arraste.parent().width()) + 40;
            val -= delta;
            if(val < -offsetMax) 
                val = -offsetMax;
            if(val > 40) 
                val = 40;
            arraste.css('left', val + "px");
            if(scrollCnt > scrollPerClick)
                clearInterval(timer);
        }, 10);
});

$(".esquerda").click(function(e) {
    var scrollCnt = 0;
    var timer = setInterval(
        function() {
            var delta = scrollPerClick / tempoScroll /10;
            scrollCnt += delta;
            var arraste = $(".menu > ul");
            var val = Number(arraste.css('left').replace("px",""));
            var offsetMax = (arraste.width()-arraste.parent().width()) + 40;
            val +=...