I really like the way Stack Overflow has done their dropdown menus on the top. Notice how you must click in order for the dropdown to trigger, but you still must hover to get the dropdown. There is also what seems to be groups - once you click, hover will activate the menus shown in the picture. It is hard to explain, but if you play around for a minute you'll see what I mean. Also, it is important that the last hovered menu will show until a user clicks off again.
Here is what I have so far; note that I almost have the same functionality, except for the last menu hovered doesn't stay dropped (it closes on mouseout when it shouldn't until off-click) and the toggle functionality is sketchy:
$(document).ready(function() {
var depressed = false;
$('.menu').click(function() {
depressed = true;
$('.menu').toggleClass('active');
});
$('.menu').hover(function() {
if (depressed) {
$('.menu').toggleClass('active');
}
});
});
ul {
margin: 0;
padding: 0;
}
ul li {
display: inline-block;
padding: 10px 20px;
background: #333;
color: #eee;
}
ul li.active:hover ul {
display: block;
}
ul li ul {
display: none;
position: absolute;
border: 2px solid #555;
}
ul li ul li {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="menu">button 1
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu">button 2
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu">button 3
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
</ul>
My JS is not cuttin git.
So, what is the best way to go about this?
I haven't peeked into the SO menu, so I don't know how they did it. But this seems to work nicely.
A click on one of the buttons opens the dropdown.
The dropdown is not closed by a 'mouseout', like in your code, but only when another menu is hovered. If you hover outside of the menu area, the lastly hovered menu remains open.
Clicking anywhere closes the menu.
So showing the menu is not directly done by using a :hover pseudo element in CSS, but by adding a class, which remains there even when the menu is unhovered. I think the net result behaves pretty close to Stack Overflow's.
$(function(){
// The event to handle clicks outside of the menu. This will close the menu.
var offEvent =
function(event){
$('.menu-bar').removeClass('active');
$(document).off('click', offEvent);
};
// The click event on the menu buttons, to toggle 'menu mode' as it were.
$(document).on('click', '.menu-bar .menu',
function(event){
event.preventDefault();
$('.menu-bar').addClass('active');
$(this).addClass('active');
// Leave menu mode by clicking anywhere of the menu.
$(document).on('click',
offEvent
);
});
// Hover toggles between the dropdowns of the separate menus.
$('.menu-bar .menu').hover(
function(event){
var $current = $(this);
$('.menu').each(
function(index, element){
var $element = $(this);
if ($element.get(0) == $current.get(0)) {
$element.addClass('active');
} else {
$element.removeClass('active');
}
});
});
});
ul {
margin: 0;
padding: 0;
}
ul li {
display: inline-block;
padding: 10px 20px;
background: #333;
color: #eee;
}
ul li ul {
display: none;
position: absolute;
border: 2px solid #555;
}
ul li ul li {
display: block;
}
.menu .dropdown {
display: none;
}
.menu-bar.active .menu.active .dropdown {
display: block;
}
.menu {
display: inline-block;
position: relative;
border: 1px solid grey;
}
.menu .dropdown {
position: absolute;
top: 100%;
left: 0;
border: 2px solid #555;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu-bar">
<li class="menu">button 1
<ul class="dropdown">
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu">button 2
<ul class="dropdown">
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu">button 3
<ul class="dropdown">
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
</ul>
$(document).ready(function() {
$('#M1').click(function() {
$('#M1').toggleClass('active');
$('#M2').removeClass('active');
$('#M3').removeClass('active');
});
$('#M2').click(function() {
$('#M2').toggleClass('active');
$('#M1').removeClass('active');
$('#M3').removeClass('active');
});
$('#M3').click(function() {
$('#M3').toggleClass('active');
$('#M1').removeClass('active');
$('#M2').removeClass('active');
});
});
ul {
margin: 0;
padding: 0;
}
ul li {
display: inline-block;
padding: 10px 20px;
background: #333;
color: #eee;
}
ul li.active ul {
display: block;
}
ul li ul {
display: none;
position: absolute;
border: 2px solid #555;
}
ul li ul li {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="menu" id='M1'>button 1
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu" id='M2'>button 2
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
<li class="menu" id='M3'>button 3
<ul>
<li>sub button 1</li>
<li>sub button 2</li>
</ul>
</li>
</ul>
This works for me.
I've just removed :hover from the end of the .active class and made an individual function for each button.
Related
i refer to this thread: JS using onclick event on li to display block
From desktop is ok but how do i do the same thing but that from the mobile you can touch the "disappearing" menu and make sure that it remains visible until the next touch?
I'm currently using this code here:
function dropdown() {
document.getElementById("Menuitems").style.display = "block";
}
#dropdown ul {
display: block;
transition-duration: 1s;
}
#dropdown ul li {
display: block;
background-color: #212121;
color: #ffffff;
}
#dropdown ul li ul {
display: none;
}
#dropdown ul li:hover>ul {
/*this is what the onclick event should do*/
display: block;
}
<div id="dropdown">
<ul>
<li onclick="dropdown()"><a>Menu</a>
<ul id="Menuitems">
<li>item 1 </li>
<li>item 2 </li>
<li>item 3 </li>
</ul>
</li>
</ul>
</div>
I just added an active class onclick .. the active class toggles on every click. and just add the same hover effect to active class
function dropdown() {
document.getElementById("Menuitems").classList.toggle("active");
}
#dropdown ul {
display: block;
transition-duration: 1s;
}
#dropdown ul li {
display: block;
background-color: #212121;
color: #ffffff;
}
#dropdown ul li ul {
display: none;
}
#dropdown ul li:hover>ul,
#dropdown ul li>ul.active{
/*this is what the onclick event should do*/
display: block;
}
<div id="dropdown">
<ul>
<li onclick="dropdown()"><a>Menu</a>
<ul id="Menuitems">
<li>item 1 </li>
<li>item 2 </li>
<li>item 3 </li>
</ul>
</li>
</ul>
</div>
I have created a website with bootstrap 3 framwork. now problem is, dropdown submenu not closed after clicking the sub-menu item. my templates uses hover function to show up sub-menu items.
I want to close the dropdown when the user clicks sub menu item.
For an example, services menu contains submenu list. when the users clicks anyone of item, entire sub-menu should be closed. how to do? any suggestions?
sitelink
jQuery( ".dropdown-menu li a" ).click(function() {
jQuery("ul.dropdown-menu").css("display", "none");
});
Use display block in the css code
.dropdown:hover .dropdown-content {
display: block;
}
.dropdown-content a:hover {background-color: #f1f1f1}
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
Link 1
Link 2
Link 3
</div>
</div>
You can use extra class to select the menu items which have dropdown element. For this example, a class "trigger" is used for defining which have child elements.
$(function(){
$(".dropdown-menu > li > a.trigger").on("click",function(e){
var current=$(this).next();
var grandparent=$(this).parent().parent();
if($(this).hasClass('left-caret')||$(this).hasClass('right-caret'))
$(this).toggleClass('right-caret left-caret');
grandparent.find('.left-caret').not(this).toggleClass('right-caret left-caret');
grandparent.find(".sub-menu:visible").not(current).hide();
current.toggle();
e.stopPropagation();
});
$(".dropdown-menu > li > a:not(.trigger)").on("click",function(){
var root=$(this).closest('.dropdown');
root.find('.left-caret').toggleClass('right-caret left-caret');
root.find('.sub-menu:visible').hide();
});
});
.dropdown-menu>li
{ position:relative;
-webkit-user-select: none; /* Chrome/Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+ */
/* Rules below not implemented in browsers yet */
-o-user-select: none;
user-select: none;
cursor:pointer;
}
.dropdown-menu .sub-menu {
left: 100%;
position: absolute;
top: 0;
display:none;
margin-top: -1px;
border-top-left-radius:0;
border-bottom-left-radius:0;
border-left-color:#fff;
box-shadow:none;
}
.right-caret:after,.left-caret:after
{ content:"";
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
display: inline-block;
height: 0;
vertical-align: middle;
width: 0;
margin-left:5px;
}
.right-caret:after
{ border-left: 5px solid #ffaf46;
}
.left-caret:after
{ border-right: 5px solid #ffaf46;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="dropdown" style="position:relative">
Click Here <span class="caret"></span>
<ul class="dropdown-menu">
<li>
<a class="trigger right-caret">Level 1</a>
<ul class="dropdown-menu sub-menu">
<li>Level 2</li>
<li>
<a class="trigger right-caret">Level 2</a>
<ul class="dropdown-menu sub-menu">
<li>Level 3</li>
<li>Level 3</li>
<li>
<a class="trigger right-caret">Level 3</a>
<ul class="dropdown-menu sub-menu">
<li>Level 4</li>
<li>Level 4</li>
<li>Level 4</li>
</ul>
</li>
</ul>
</li>
<li>Level 2</li>
</ul>
</li>
<li>Level 1</li>
<li>Level 1</li>
</ul>
</div>
try this jquery
$( ".dropdown" ).click(function() {
$(".dropdown").removeClass("open");
$("#menulink + .dropdown-menu").css("display", "none");
});
remove the open class of dropdown when a link is clicked
I am attempting to make a dropdown menu that when clicked stays down but also, when clicking anywhere within the dropdown area, it will not slide up. Only when clicked elsewhere on the page should it disappear.
I am struggling to make this happen though. You can see what I am doing here:
HTML
<nav id="moo">
<ul>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</li>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
</ul>
</div>
</li>
</ul>
</nav>
CSS
ul { padding: 0px; margin: 0px; }
li { display: inline; }
nav li { position: relative; }
nav i { cursor: pointer; font-weight: bold; background-color: red;padding: 5px; }
.dropdown { display: none; position: absolute; border:1px solid #ccc; padding: 10px; }
.dropdown li {
display: block;
}
SCRIPT
$('nav li').click(function () {
var $childDropdown = $(this).find('.dropdown');
if ($childDropdown.is(':visible')) {
$('.dropdown').slideUp(300);
} else {
$('.dropdown').slideUp(300);
$childDropdown.slideDown(300);
}
});
/* Anything that gets to the document
will hide the dropdown */
$(document).click(function(){
$(".dropdown").hide();
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$("nav").click(function(e){
e.stopPropagation();
});
Here is fiddle version:
http://jsfiddle.net/susannalarsen/buNq9/
You will need to work with the event target property and traverse up its parents to find out what element has triggered the event. if it's an element inside ".dropdown" class, then no sliding-up should be applied, otherwise close dropdown.
example
$('nav > ul > li').click(function (e) {
var $childDropdown = $(this).find('.dropdown');
if ($childDropdown.is(':visible')) {
var target = $(e.target);
if (!$(target).parents(".dropdown").length) {
$('.dropdown').slideUp(300);
}
} ...
Notice that i changed the selection in $('nav > ul > li'), which will apply only to the LI elements of the upper level.
I am using stopPropegation to aid me in the way my dropdowns work.
I am using it for multiple dropdowns to help me keep the dropdown open but if the user clicks anywhere else on the page then it will slide up the menu.
HTML
<nav id="moo">
<ul>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</li>
<li>Item 1 <i>o</i>
<div class="dropdown">
<ul>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
</ul>
</div>
</li>
</ul>
</nav>
<div class="clear"></div>
<div id="login-top">Login</div>
<div id="user">roooar</div>
CSS
ul { padding: 0px; margin: 0px; }
li { display: inline; }
nav li { position: relative; }
nav i { cursor: pointer; font-weight: bold; background-color: red;padding: 5px; }
.dropdown { display: none; position: absolute; border:1px solid #ccc; padding: 10px; }
.dropdown li {
display: block;
}
.clear {
clear:both;
}
#login-top {
background:blue;
padding:10px;
color:white;
margin-top:30px
}
#user {
background:pink;
margin-top:10px;
padding:50px;
}
SCRIPT
$('#login-top').click(function () {
var $user = $('#user');
if ($('#user').is(':visible')) {
$user.slideUp(300);
} else {
$user.slideUp(300);
$user.slideDown(300);
}
});
$('nav > ul > li').click(function (e) {
var $childDropdown = $(this).find('.dropdown');
if ($childDropdown.is(':visible')) {
var target = $(e.target);
if (!$(target).parents(".dropdown").length) {
$('.dropdown').slideUp(300);
}
} else {
$('.dropdown').slideUp(300);
$childDropdown.slideDown(300);
}
});
/* Anything that gets to the document
will hide the dropdown */
$(document).click(function () {
$(".dropdown").hide();
$("#user").slideUp();
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$("nav, #login-top, #user").click(function (e) {
e.stopPropagation();
});
I have 2 questions really about this.
Say if I click open the dropdown menu because I have included certain elements to be exempt from clicking elsewhere on the page - If I click anywhere else it will slide back up exactly how I want.
However, if I happen to click on the #login-top this will not make it slide up as I have added it to the code for the stopPropagation
Is there a may of making it work so that when ".dropdown" is active then you can click absolutely everywhere (including on the <div id='login'> And then when "#login" and "#user" is active you can click anywhere on "nav" and it will still slide up the div?
Is it the right thing to be doing by grouping all the classes and id's into the code:
$("nav, #login-top, #user").click(function (e) {
e.stopPropagation();
});
(I am struggling to explain this but hopefully you can see what I mean if you look at the fiddle version)
http://jsfiddle.net/susannalarsen/Nt2ZM/1/
JSFiddle # http://jsfiddle.net/UqyAq/
html -
<nav>
<ul>
<li>Button 1</li>
<li>Button 2
<ul>
<li>Sub-Button 1</li>
<li>Sub-Button 2</li>
<li>Sub-Button 3</li>
</ul>
</li>
<li>Button 3</li>
<li>Button 4</li>
<li>Button 5</li>
</ul>
</nav>
css -
* {
margin: 0;
padding: 0;
}
nav {
height: 100%; width: 18%;
position: absolute;
}
nav ul {
list-style-type: none;
font-family: 'Universal Accreditation', Serif;
font-size: 18pt;
letter-spacing: 1px;
font-variant: small-caps;
color: black;
}
nav ul ul {
display: none;
}
nav ul li {
display: block;
}
nav ul li:hover ul {
display: block;
}
Basically, you are looking at a simple un-ordered list drop down menu. I am trying to figure out what I need to use to create an easing effect on the drop down of the second tier. Hovering over 'Button 2' will bring up the sub-menu.
Notice how its a one jump movement. How would I slow it down? Maybe look like the sub-menu is sliding out from under 'Button 2'?
Should I use javascript or css?
Use this code..
HTML:
<ul id="menu">
<li>Link 1
<ul class="submenu">
<li>Sub Link 1.1
<ul class="submenu">
<li> Sub Link 1.1.1</li>
<li> Sub Link 1.1.2</li>
</ul>
</li>
<li>Sub Link 1.2</li>
<li>Sub Link 1.3</li>
</ul>
</li>
<li>Link 2
<ul class="submenu">
<li>Sub Link 2.1
<ul class="submenu">
<li> Sub Link 2.1.1</li>
<li> Sub Link 2.1.2</li>
</ul>
</li>
<li>Sub Link 2.2</li>
</ul>
</li>
</ul>
CSS:
.submenu
{
display: none;
}
#menu li ul{
margin-left:15px;
}
JQUERY:
$(document).ready(function () {
$('#menu > li').hover(function () { $(this).find("ul:first").show(); },
function () { $(this).find("ul:first").hide(); }
);
$('#menu li li').hover(function () {
$('ul:first', this).each(function () {
var p = $(this).parent();
$(this).css('top', p.position().top)
.css('left', p.position().left + p.width())
.show();
});},
function () { $('ul:first', this).hide(); }
);
});