Search code examples
jqueryhideshowsubmenu

jQuery complex hide show submenu


I can't figure out a proper way to accomplish all the logic needed. The submenus needs to be outside of its menu link root, because of layout purposes. The logic needed is:

When the submenu should OPEN:

  1. in a touch device when the user tap on link
  2. in a pointer decide when the user hover on link
  3. When the menu is opened, the link and the sub-menu must get the "active" class.

When the submenu should CLOSE:

  1. When the "Close" button is clicked (its located inside submenu)
  2. When another menu is open, the first menu should close
  3. In a touch device, When you click anywhere outside the submenu
  4. In a pointer device, when the mouse leaves the submenu area

EDITED: THIS IS THE FINAL CODE WORKING 100% after @SilverSurfer awnser and some ajusts


$(".sub-menu").hide()

$("a.close-bt").click(function(){
    $(this).closest(".sub-menu").hide()
    $(this).closest(".sub-menu").removeClass("active")
    $(this).closest(document).find("a.menu-item").removeClass("active")
});

$(document).on('click mouseover', "ul.menu > a", function () {
    $("ul.menu > a").removeClass("active")
    $(".sub-menu").hide()
    var target = "."+$(this).attr("id")
    $(target).addClass("active")
    $(this).addClass("active")
    $(target).show()
});
$(".sub-menu").mouseleave(function() {
    $(this).hide()
    $(this).removeClass("active")
    $(this).closest(document).find("a.menu-item").removeClass("active")
});
// FUNCTIONAL STYLES

.menu {
	z-index: 2;
}
.menu a {
}
.sub-menu {
	//visibility: hidden;
	//visibility: show;
}
.close-bt {
	
}


// VISUAL STYLES, PLZ IGNORE
.menu {
}
.menu a {
	margin-right: 30px;
	background: green;
	display: inline-block;
	padding: 20px;
	color: white;
}
.menu a.active {
	background: red;
}
.sub-menu {
	width: 100px;
	height: 100px;
	background: lightblue;
	border: 2px solid black;
	z-index: 1;
	position: relative;
}
.sub-menu.active {
	visibility: show;
	background: blue;
}
.close-bt {
	background: red;
	color: white;
	padding: 10px;
	position: absolute;
	right: 10px;
	bottom: 10px;
}
ul { margin: 0; left: 0; padding: 0; }


.container  { position: absolute; top: 50px; left: 0; } 
.item1 { position: absolute; top: 10px; left: 0; }
.item2 { position: absolute; top: 10px; left: 110px; }
.item3 { position: absolute; top: 10px; left: 220px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul class="menu">
	<a class="menu-item" id="item1" href="javascript:void(0);">Link 1</a>
	<a class="menu-item" id="item2" href="javascript:void(0);">Link 2</a>
	<a class="menu-item" id="item3" href="javascript:void(0);">Link 3</a>
</ul>


<div class="container">
	<div class="sub-menu item1">
    <a class="close-bt" href="javascript:void(0);">Close</a>
		Sub-menu 1
	</div>
	<div class="sub-menu item2">
    <a class="close-bt" href="javascript:void(0);">Close</a>
		Sub-menu 2
	</div>
	<div class="sub-menu item3">
    <a class="close-bt" href="javascript:void(0);">Close</a>
		Sub-menu 2
	</div>
</div>


Solution

  • Is this what are you looking for?

    $(".sub-menu").hide()
    
    $("a.close-bt").click(function(){
        $(this).closest(".sub-menu").hide()
        $(this).closest(".sub-menu").removeClass("active")
        $(this).closest(document).find("ul").removeClass("active")
    });
    
    $(document).on('click mouseover', "ul > a", function () {
        $(".sub-menu").hide()
        var target = "."+$(this).attr("id")
        $(target).addClass("active")
        $(this).closest("ul.menu").addClass("active")
        $(target).show()
    });
    // FUNCTIONAL STYLES
    
    .menu {
    	z-index: 2;
    }
    .menu a {
    }
    .sub-menu {
    	//visibility: hidden;
    	//visibility: show;
    }
    .close-bt {
    	
    }
    
    
    // VISUAL STYLES, PLZ IGNORE
    .menu {
    }
    .menu a {
    	margin-right: 30px;
    	background: green;
    	display: inline-block;
    	padding: 20px;
    	color: white;
    }
    .menu a.active {
    	background: red;
    }
    .sub-menu {
    	width: 100px;
    	height: 100px;
    	background: lightblue;
    	border: 2px solid black;
    	z-index: 1;
    	position: relative;
    }
    .sub-menu.active {
    	visibility: show;
    	background: blue;
    }
    .close-bt {
    	background: red;
    	color: white;
    	padding: 10px;
    	position: absolute;
    	right: 10px;
    	bottom: 10px;
    }
    ul { margin: 0; left: 0; padding: 0; }
    
    
    .container  { position: absolute; top: 50px; left: 0; } 
    .item1 { position: absolute; top: 10px; left: 0; }
    .item2 { position: absolute; top: 10px; left: 110px; }
    .item3 { position: absolute; top: 10px; left: 220px; }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <ul class="menu">
    	<a id="item1" href="javascript:void(0);">Link 1</a>
    	<a id="item2" href="javascript:void(0);">Link 2</a>
    	<a id="item3" href="javascript:void(0);">Link 3</a>
    </ul>
    
    
    <div class="container">
    	<div class="sub-menu item1">
        <a class="close-bt" href="javascript:void(0);">Close</a>
    		Sub-menu 1
    	</div>
    	<div class="sub-menu item2">
        <a class="close-bt" href="javascript:void(0);">Close</a>
    		Sub-menu 2
    	</div>
    	<div class="sub-menu item3">
        <a class="close-bt" href="javascript:void(0);">Close</a>
    		Sub-menu 2
    	</div>
    </div>