I need to add a second level of submenus here.
Is there a dynamic solution, so only one submenu is opened, when clicking on the link?
And when clicking a link to a submenu (in the first submenu), then open this one?
And so on…
I already changed the jsfiddle a little, to have one level of sublevels more: http://jsfiddle.net/cRsZE/363/
Working example with one level of submenus: JSFiddle Demo
HTML:
<ul id="nav">
<li>Home</li>
<li class="parent">About
<ul class="sub-nav">
<li>Johnny</li>
<li>Julie</li>
<li>Jamie</li>
</ul>
</li>
<li>Contact</li>
</ul>
CSS:
#nav ul.sub-nav {
display: none;
}
#nav ul.visible {
display: block;
}
jQuery:
$(document).ready(function() {
$('.parent').click(function() {
$('.sub-nav').toggleClass('visible');
});
});
Source: Creating Drop Down Menu on click CSS
Try,
CSS:
.hidden {
display: none;
}
JS:
$('ul ul').addClass('hidden');
$(document).ready(function () {
$('.parent').click(function (e) {
e.stopPropagation();
$(this).find('ul').first().toggleClass('hidden');
});
});
DEMO
Related
I have a menu where there are the heading and the submenus. Whenever the user hovers over the heading, submenus show up.
And whenever any of the items in submenus is clicked, the submenu is set to hidden using Javascript. Now, when the user hovers over the menu, the submenus don't show up! Please help me to fix this.
function closesSan() {
document.getElementsByClassName('submenu')[0].style.setProperty('display', 'none', 'important');
}
#main:hover .submenu {
display: block!important;
}
<ul>
<li id="main">
List
<ul class="submenu" style="display: none;">
<li onclick="closesSan()">Bacon</li>
<li onclick="closesSan()">Tuna</li>
<li onclick="closesSan()">Chicken</li>
</ul>
</li>
</ul>
I had to write some additional code to get the desired result. Actually, the base problem in your code was important and property {both works same} in sense both get prioritized by code.
So to get rid of I have added an additional class on click and removing that class on every new hover. Hope it will satisfy the needs.
var main = document.getElementById("main");
main.onmouseover = function() {
document.querySelector('.submenu').classList.remove("displayNoneImp");
}
function closesSan() {
document.querySelector('.submenu').classList.add("displayNoneImp");
}
.submenu {
display: none;
}
#main:hover .submenu {
display: block;
}
.displayNoneImp {
display: none !important;
}
<ul>
<li id="main">
List
<ul class="submenu">
<li onclick="closesSan()">Bacon</li>
<li onclick="closesSan()">Tuna</li>
<li onclick="closesSan()">Chicken</li>
</ul>
</li>
</ul>
Since you don't use a pure CSS implementation, use event listeners and avoid using !important whenever possible:
var main = document.querySelector('#main');
var submenu = document.querySelector('.submenu');
var items = document.querySelectorAll('#main li');
main.addEventListener('mouseover', function () {
submenu.style.display = 'block';
});
main.addEventListener('mouseout', function () {
submenu.style.display = 'none';
});
items.forEach(function(item) {
item.addEventListener('click', function () {
console.log('clicked on:', item)
submenu.style.display = 'none';
});
});
.submenu {
display: none;
}
<ul>
<li id="main">
List
<ul class="submenu">
<li>Bacon</li>
<li>Tuna</li>
<li>Chicken</li>
</ul>
</li>
</ul>
When Using !important is The Right Choice
You can try something simple like this:
function closesSan() {
document.getElementsByClassName('submenu')[0].classList.add("hide");
setTimeout(function() {
document.getElementsByClassName('submenu')[0].classList.remove("hide");
},100)
}
#main .submenu {
display: none;
}
#main:hover .submenu {
display: block;
}
#main .submenu.hide {
display: none;
}
<ul>
<li id="main">
List
<ul class="submenu" >
<li onclick="closesSan()" >Bacon</li>
<li onclick="closesSan()">Tuna</li>
<li onclick="closesSan()">Chicken</li>
</ul>
</li>
</ul>
use visibility instead of display
visibility: hidden;
save those kittens
I have a link and div within each of my list items. If the link HAS an href then I want to make sure the div is hidden within its list item and the link appear just normal.
However if the link DOES NOT have a href (e.g. href=""), then I want to add the class .show to the div so I can show it. I also want to hide the link at the same time.
Or is there a better way to do this? Thanks
<style>
.nolinkdiv { display:none; }
.show { display:block!important; }
</style>
<ul>
<li>
Register
<div class="nolinkdiv">Register Coming Soon</div>
</li>
<li>
Register
<div class="nolinkdiv">Register Coming Soon</div>
</li>
</ul>
You don't need JavaScript for this:
.nolinkdiv { display:none; }
ul li a[href=""] {
display: none;
}
ul li a[href=""] + div {
display: block;
}
This is actually the proper way of doing it to hide via CSS only:
ul li a {
display: none;
}
ul li a[href^="https:"],
ul li a[href^="http:"] {
display: block; //This can be anything else rather than block, such as grid etc.
}
$( document ).ready(function() {
$('ul li').each(function(idx, li) {
var LI = $(this);
var hrefValue = LI.find("a").attr('href');
if(hrefValue) {
LI.find("div").hide()
} else {
LI.find("a").hide()
}
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
Register
<div class="">Register Coming Soon</div>
</li>
<li>
Register
<div class="">Register Coming Soon</div>
</li>
</ul>
I have created a simple dropdown menu with jquery
https://jsfiddle.net/pmksgz3w/
HTML
<ul>
<li>Page A</li>
<li>Page B
<ul>
<li>Dropdown</li>
<li>Dropdown</li>
</ul>
</li>
</ul>
Jquery
$(document).ready(function(){
$('ul> li').hover(function() {
$(this).find('ul').slideToggle();
});
});
When I hover over Page B, then the dropdown menu is shown. If I move the curser from Page B very slowly to the right (see picture) then the drop-down menu will close, since the li is not hovered for a short moment. How can I prevent that the dropdown menu will instantly close?
An even worse problem happens if I move the cursor extremely fast to the dropdown menu. Because then, the dropdown menu will slideUp and slideDown in an infinite loop.
I found at How to tell .hover() to wait? a promising solution from 2009 but the answer does not work when I try it,(Edit note: It works now, see edit below). Further it is mentioned that one should use hoverIntend plugin. I downloaded the plugin and changed my jQuery code to
$(document).ready(function(){
$('ul> li').hoverIntend(function() {
$(this).find('ul').slideToggle();
});
});
and although it improves some things, the above problem that it instantly closes and the infinite loop remains. How can I solve this problem?
Edit: I managed to solve the first problem! Now the dropdown does not close instantly!
https://jsfiddle.net/5sxvsu8w/
I had to change the jQUery code as follows:
$(document).ready(function(){
var timer;
$('ul> li').hover(function() {
clearTimeout(timer);
$(this).find('ul').slideDown('fast');
}, function() {
var list = $(this).find('ul');
timer= setTimeout(function() {
list.slideUp('fast');
}, 2000);
});
});
However, the infinite loop problem remains.
The solution you found in here is usefull, this javascript code maybe can help:
$(document).ready(function(){
$('.menu li').hover(
function () {
$('.sub', this).stop().slideDown(650);
},
function () {
$('.sub', this).stop().slideUp(650);
}
);
});
/*$('ul >li').hover(function() {
clearTimeout($(this).data('timeout'));
$('li > ul').slideDown('fast');
}, function() {
var t = setTimeout(function() {
$('li > ul').slideUp('fast');
}, 650);
$(this).data('timeout', t);
});*/
li{
list-style-type:none;
display: inline-block;
position: relative;
padding: 20px;
background-color: #08c;
}
li ul li{
min-width:200px;
}
li ul{
margin:0;
padding:0;
position: absolute;
top: 100%;
left:0;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="menu">
<li>Page A</li>
<li>Page B
<ul class="sub">
<li>Dropdown</li>
<li>Dropdown</li>
</ul>
</li>
</ul>
EDIT: I have changed my javascript code after some reseach; this solution unfortunately does not solve completely the first problem (it is still based on a timer) but avoids the infinite loop.
I'm working on http://www.variied.com/market/men/. I'm trying to create a toggle dropdown menu on the sidebar that is triggered when someone hits the "Tops" link on the sidebar, which will then toggle the content in the sub-menu to be displayed. Here's my current code
<style>
ul.category ul.sub-menu ul.sub-menu li a{
display:none
}
</style>
<script>
jQuery(document).ready(function() {
jQuery("#menu-item-746").click(function() {
jQuery(this).next("ul.category ul.sub-menu ul.sub-menu li a").toggle();
return false;
});
});
</script>
There are a few issues in this fiddle:
You have a class called #submenu it should just be submenu
You're passing the event so you can use e.preventDefault() (unless you prefer return false)
I would suggest setting the subnav ul to display: none and just toggling that and I would use slideToggle for a nicer effect.
JS
$("#menu-item-746").click(function(e) {
e.preventDefault();
$(this).next("ul").slideToggle();
});
HTML
<ul class="submenu">
<li id="menu-item-746">Test Item</li>
<ul>
<li>Test1</li>
<li>Test2</li>
</ul>
</ul>
CSS
.submenu ul{
display: none;
}
FIDDLE
UPDATE
I looked at your HTML on your site and it appears that your ul subnav is a child of your li not a sibling (it was a sibling in your fiddle). Try this:
$(this).find("ul").slideToggle();
Also from the code you have provided you are targeting an id which means this would only work for that 1 element. It appears the ones with a subnav have a class called .menu-item-has-children so I would target that, like so:
$(".sub-menu .menu-item-has-children").click(function(e) {
e.preventDefault();
$(this).find("ul.sub-menu").slideToggle();
});
NEW UPDATE
Target the a instead then:
$(".sub-menu .menu-item-has-children").on("click", " a:first", function(e) {
e.preventDefault();
$(this).siblings("ul.sub-menu").slideToggle();
});
If someone could help me point in the right direction that would be awesome as I have been looking for a solution to this issues for hours.
http://jamessuske.com/will/
I have a menu with 3 menu items on it. if you hover over the last two menu items, a div with items from a different list appear. That part works fine, but if I go to roll over the other menu items from another list, they disappear again.
This is my JavaScript:
<script type="text/javascript">
function showGalleryNav(){
document.getElementById('headerNavGallery').style.display = "";
}
function showInfoNav(){
document.getElementById('headerNavInfo').style.display = "";
}
function hideGalleryNav(){
document.getElementById('headerNavGallery').style.display = "none";
}
function hideInfoNav(){
document.getElementById('headerNavInfo').style.display = "none";
}
</script>
And The HTML
<div class="headerNav">
<ul>
<li>Home</li>
<li>Gallery</li>
<li>Info</li>
</ul>
</div><!--headerNav-->
<div class="headerNavGallery" id="headerNavGallery" style="display:none;">
<ul>
<li>Categoies</li>
<li>Products</li>
</ul>
</div><!--headerNavGallery-->
<div class="headerNavInfo" id="headerNavInfo" style="display:none;">
<ul>
<li>William Ruppel</li>
<li>CV</li>
<li>Artist Bio</li>
<li>Video</li>
<li>Contact</li>
</ul>
</div><!--headerNavInfo-->
I've tried different Attributes, but none of them are working, I have also tried switching to jQuery with
$('#headerNavGallery").css("display", "");
also didn't work,
Any ideas would be greatly apperiated.
Actually what you are trying to accomplish is all css-only doable but not with that markup structure. First you need to nest your lists.
<ul class="menu">
<li>item 1</li>
<li>
item 2 with sub
<ul>
<li>sub menu item 1</li>
<li>sub menu item 2</li>
... so on ..
</ul>
</li>
</ul>
some css
.menu li {
position: relative;
}
.menu li ul {
position: absolute;
top: 30px; /* the height of the root level item */
display: none;
}
.menu li li {
position: static; /* or you could float these for horizontal menu */
}
.menu li:hover ul {
display: block;
}
These are pretty much the basics. But I strongly suggest you go and study superfish menu as it's jquery drop drop menu but it degrades nicely with js off, so you could just study the css of it. http://users.tpg.com.au/j_birch/plugins/superfish/
Check that typeo, nvm...
Setting the display property should always have a value "none" or "block", empty("") is a bad reset... try this:
<script>
$(".galleryNavToggle").on("mouseenter mouseleave", function(event){
var headNavGal = $("#headerNavGallery");
if(event.type === "mouseenter"){
headNavGal.show();
}else if(event.type ==="mouseleave" &&
((event.relatedTarget !== headNavGal[0] && $.inArray(event.relatedTarget, headNavGal.find("*")) <=0) ||
$.inArray(event.relatedTarget, $(".galleryNavInfoToggle")) > 0)){
headNavGal.hide();
}
});
$("#headerNavGallery").on("mouseleave", function(event){
var headNavGal = $(this);
if(event.type ==="mouseleave"){
headNavGal.hide();
}
});
</script>
HTML
<div class="headerNav">
<ul>
<li>Home</li>
<li><a href="" class='galleryNavToggle'>Gallery</a></li>
<li><a href="" class='galleryNavInfoToggle'>Info</a></li>
</ul>
</div><!--headerNav-->
<div class="headerNavGallery" id="headerNavGallery" style="display:none;">
<ul>
<li>Categoies</li>
<li>Products</li>
</ul>
</div><!--headerNavGallery-->
AND CSS
.headerNav{
border:thin solid black;
float:left;
}
.headerNavGallery{
float:left;
border:thin solid black;
margin-left:-1px;
}
1) Gallery
You don't need to specify javascript:. This is redundant.
2) It is working exactly the way you programmied it to work. When you mouse-out, it disappears.
3) You have code for "headerNavInfo" but no matching HTML.