I have basic markup for a drop down nav, nested lists.
The user will click on the top nav item, which will open up the sub nav, but my sub nav links aren't working.
It is in a CMS so I must have the links for the placeholder pages there.
Markup:
<ul class="navtop">
<li>Who
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Long Sub Item 3</li>
<li>Sub Item 4</li>
</ul>
</li>
<li>What
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Long Sub Item 3</li>
<li>Sub Item 4</li>
</ul>
</li>
</ul>
Javascript:
$(".navtop li").click(function(){
$(this).toggleClass("show");
$(this).siblings(".show").toggleClass("show");
return false;
});
css:
#headernav .navtop li.show ul
{
display: block;
}
I tried adding a 'return true' for $(".navtop li ul li a") but it didn't work.
Suggestions?
Why are you return false to the LI click? I believe that's the problem.
If you take that out, everything should work fine.
If that doesn't work, bear in mind you're attaching the click event to every LI instead of just the top level LIs. Try this instead:
$(".navtop > li").click(function(){
$(this).toggleClass("show");
$(this).siblings(".show").toggleClass("show");
});
Turns out this worked:
$(".navtop > li > a").click(function(){
$(this).parent('li').toggleClass("show");
$(this).parent('li').siblings(".show").toggleClass("show");
return false;
});
Related
I've been trying to figure it out for a few hours now and as i'm pretty new to jQuery itself and i'm definetely still a beginner i really need some help with this. I try to create a navigation with a submenu in it. Everything is working as intended but i am missing the way i can stop the list items of the submenu from toggling.
HTML:
<nav>
<ul id="site-nav">
<li>Main Nav Item 1</li>
<li>Main Nav Item 2 (with submenu)
<ul>
<li>Submenu Item 1</li>
<li>Submenu Item 2</li>
<li>Submenu Item 3</li>
</ul>
</li>
<li>Main Nav Item 3 (with submenu)
<ul>
<li>Submenu Item 1</li>
<li>Submenu Item 2</li>
</ul>
</li>
<li>Main Nav Item 4</li>
<li>Main Nav Item 5</li>
</ul>
</nav>
JQuery (submenu part):
$(document).ready(function() {
var subnavArrow = ['<div id="subnavArrow"></div>'];
subpull = $('header nav ul li');
submenu = $('header nav ul li ul');
submenuitems = $('header nav ul li ul li');
subpull.has('ul').prepend(subnavArrow);
$('header nav ul li').has('ul').click(function() {
$(this).children('ul').toggle('slow');
});
});
If you didn't catch what i mean, i try to explain it as thoroughly as i can:
I want to open the Main Nav Item 2's subitems per click on it (Main Nav Item 2). This is working as intented and i can also close it again, but if i click on a Submenu Item of "Main Nav Item 2" it will close down the Main Nav Item 2's submenu.
You can check whether you have clicked on the anchor or div element like
$(document).ready(function() {
var subnavArrow = ['<div id="subnavArrow"></div>'];
subpull = $('header nav ul li');
submenu = $('header nav ul li ul');
submenuitems = $('header nav ul li ul li');
subpull.has('ul').prepend(subnavArrow);
$('header nav ul li').has('ul').click(function(e) {
if ($(e.target).closest('li').is(this)) {
$(this).children('ul').toggle('slow');
}
});
});
#subnavArrow:after {
content: '<<'
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>
<nav>
<ul id="site-nav">
<li>Main Nav Item 1
</li>
<li>Main Nav Item 2 (with submenu)
<ul>
<li>Submenu Item 1
</li>
<li>Submenu Item 2
</li>
<li>Submenu Item 3
</li>
</ul>
</li>
<li>Main Nav Item 3 (with submenu)
<ul>
<li>Submenu Item 1
</li>
<li>Submenu Item 2
</li>
</ul>
</li>
<li>Main Nav Item 4
</li>
<li>Main Nav Item 5
</li>
</ul>
</nav>
</header>
Don't append #ID elements. ID should be unique. Use classes instead .subnavArrow
Refer in jQuery to #site-nav as the parent
Use Event.stopPropagation() (if you'll use more nested li>ul)
Always assign your var to variables, or concatenate using ,
$(function() { // DOM ready
var $LIsub = $("#site-nav li:has(ul)");
$LIsub.children("a").append('<span class="subnavArrow"/>');
$LIsub.click(function(e) {
e.stopPropagation();
$(this).find('> ul').slideToggle('slow');
});
});
#site-nav li ul{
display:none;
}
.subnavArrow:after{
content:"\25BC"
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>
<nav>
<ul id="site-nav">
<li>Main Nav Item 1</li>
<li>Main Nav Item 2
<ul>
<li>Submenu Item 1</li>
<li>Submenu Item 2</li>
<li>Submenu Item 3</li>
</ul>
</li>
<li>Main Nav Item 3
<ul>
<li>Submenu Item 1</li>
<li>Submenu Item 2</li>
</ul>
</li>
<li>Main Nav Item 4</li>
<li>Main Nav Item 5</li>
</ul>
</nav>
</header>
The problem with your code is that when you click on a submenu <li>, the click event propagates to the parent <li>, and triggers the function hiding the <ul>.
A solution could be to move the .has('ul') part of your click listener inside the callback :
$(document).ready(function() {
var subnavArrow = ['<div id="subnavArrow"></div>'];
subpull = $('header nav ul li');
submenu = $('header nav ul li ul');
submenuitems = $('header nav ul li ul li');
subpull.has('ul').prepend(subnavArrow);
$('header nav ul li').click(function(e) {
e.stopPropagation();
if ($(this).has('ul')) {
$(this).children('ul').toggle('slow');
}
});
});
This way, the listener also listens for the clicks on the submenus, and you can prevent the event from propagating to the parent with e.stopPropagation();
You can sere this solution on this JSFiddle : https://jsfiddle.net/9ejpLmLf/
Very simple code
=============================
<pre>
$(document).ready(function() {
var subnavArrow = ['<div id="subnavArrow"></div>'];
subpull = $('header nav ul li');
submenu = $('header nav ul li ul');
submenuitems = $('header nav ul li ul li');
subpull.has('ul').prepend(subnavArrow);
$('header nav ul li a').click(function() {
$(this).siblings('ul').toggle('slow');
});
});
</pre>
I have menu defined with UL, LI... up to max one submenu:
ul
li: item 1
li: item 2
ul
li: item 2.1
li: item 2.2
li: item 3
ul
li: item 3.1
li: item 3.2
li: item 3.3
What I would like to achieve is to show submenu in a way that "sub menu item container" will slide to the next submenu when clicked. In example above this would mean:
when user clicks item 2, container with sub items will show
when user clicks item 3, container with somehow slide/animate/transition from item 2 to item 3, changing sub items
This transition should only happen if sub menu container is already visible... if not, it just shows up next to clicked menu item.
I am not sure how to approach this problem and would like your help on it.
Thank you!
EDIT:
This is hover enabled sample, no JS (I know onclick is not supported in CSS, but I can handle this later):
http://codepen.io/anon/pen/HDinB
This shows a bottom aligned main menu items. Each main menu item can have sub items (this is only one level deep menu, there will be no more sublevels). Submenu will contain no more than max 9 items which will fit into a box (black box you see). What I want is that subitems apear "in" that box, but when new main item with submenu items is selected this box will slide (if already visible) to the new position and kind of be wrapper for new subitems. Will this be a floating box, or real container, or something 3rd, I don't know because I don't realy know what would be best way to handle this.
I'm absolute no jQuery expert, and I presume that jQuery is okay for you.
I created you this function. When a submenu is expanded, the class expand is assigned to it.
When a link is clicked, the function will check if it has the expand class, if so, it will close the submenu. If not, all the other expand classes will be closed (if exist) and the submenu will be shown.
HTML:
<ul>
<li>item 1</li>
<li>item 2
<ul>
<li>item 2.1</li>
<li>item 2.2</li>
</ul>
</li>
<li>item 3
<ul>
<li>item 3.1</li>
<li>item 3.2</li>
<li>item 3.3</li>
</ul>
</li>
</ul>
CSS:
li ul {
display: none;
}
jQuery:
$(document).ready(function() {
$("li:has(ul) a").on('click', function(e) {
e.preventDefault();
var ul = $(this).parent().find('ul');
if( ul.hasClass('expand') ) {
ul.removeClass('expand').slideToggle()
}
else {
$('.expand').removeClass('expand').slideToggle();
ul.addClass('expand').slideToggle();
}
});
});
jsFiddle DEMO.
Hope it suits you, or at least helps you on your way.
<ul class="menu">
<li>item 1</li>
<li>item 2
<ul class="sub-menu">
<li>item 2.1</li>
<li>item 2.2</li>
</ul>
</li>
<li>item 3
<ul class="sub-menu">
<li>item 3.1</li>
<li>item 3.2</li>
<li>item 3.3</li>
</ul>
</li>
</ul>
<style type="text/css">
ul li{display:inline-block; position:relative;}
ul li ul{display:none;width:100%; position:absolute; white-space: nowrap;margin:0px;padding:0px;top:20px;}
ul li ul li{ display:block;}
</style>
<script type="text/javascript">
$(document).ready(function(){
$(".menu li").click(function(){
$(".menu li ul").slideUp();
if($(this).find("ul").css("display")=='block')
{
$(this).find("ul").slideUp();
}
else
{
$(this).find("ul").slideDown();
}
});
});
</script>
I have a list with different levels of depth:
<ul id="top-level" class="top-level">
<li>Item 1</li>
<li>Item 2
<ul class="sub-menu">
<li>Sub item 1</li>
<li>Sub item 2</li>
<li>Sub item 3
<ul class="sub-menu">
<li>Subsub item 1</li>
<li>Subsub item 2</li>
</ul>
</li>
<li>Sub item 4</li>
</ul>
</li>
<li>Item 3</li>
</ul>
I am using the following jquery script to add a class to the parents:
$("ul li ul").parent().addClass("menuparent");
Is there a way to add this class only to the top level parent li's and a different class for all other (deeper) parent li's?
Just use the > selector from your top level ul.
Based on your current selector:
$("ul.top-level > li > ul").parent().addClass("menuparent");
Or for li only:
$("ul.top-level > li").parent().addClass("menuparent");
For top level lis
$("#top-level > li").addClass("menuparent");
and for lower level li
$("#top-level li li").addClass("someotherclass");
If I understand correctly, people are not giving you answers for locating the deeper parent li's, here's my take:
$("ul.top-level > li > ul").find('li > ul').parent().addClass("deeper-parent-li");
I have a nav built with a list and sub nav as lists inside a parent list. The sub nav resides in the next list item to it's corresponding main nav link:
This sits in a div with an id of 'nav'
<ul>
<li>Nav main 1</li>
<li>
<ul>
<li>sub 1</li>
<li>sub 2</li>
<li>sub 3</li>
<li>sub 4</li>
</ul>
</li>
<li>Nav main 2</li>
<li>
<ul>
<li>sub 1</li>
<li>sub 2</li>
<li>sub 3</li>
<li>sub 4</li>
</ul>
</li>
</ul>
Currently I have the following jquery:
$(document).ready(function() {
$("#nav ul li a[href^='#']").each(function(){
if ($(this).next().is(':visible')) {
$(this).next().hide();
} else {
$("#nav ul li a[href^='#']").each(function(){
$(this).next().hide();
});
$(this).next().show();
}
});
I thought this would work to make all the sub menu's hide and then show the one that had been clicked on. For some reason nothing happens. I have checked the console (firebug) and there is no error shown.
Getting frustrated with it now! :-/
EDIT: Here is the answer:
$(document).ready(function() {
$("#nav ul li a[href^='#']").each(function(){
$(this).parent().next().hide();
$(this).click(function() {
if ($(this).parent().next().is(':visible')) {
$(this).parent().next().hide();
} else {
$("#nav ul li a[href^='#']").each(function(){
$(this).parent().next().hide();
});
//then reshow and label the clicked nav
$(this).parent().next().show();
}
});
});
});
HTML:
<div id="nav">
<ul>
<li>
Nav main 1
<ul>
<li>sub 1</li>
<li>sub 2</li>
<li>sub 3</li>
<li>sub 4</li>
</ul>
</li>
<li>
Nav main 2
<ul>
<li>sub 1</li>
<li>sub 2</li>
<li>sub 3</li>
<li>sub 4</li>
</ul>
</li>
</ul>
</div>
JavaScript:
var s = $('#nav ul ul').hide();
$('#nav a').click(function() {
var u = $(this).next();
u.is(':visible') ? u.hide() : ( s.hide(), u.show() );
return false;
});
Live demo: http://jsfiddle.net/Tq6LM/1/
Never mind... I have figured it out. Writing it out again must have helped. I needed to call the .parent()
Seems that i was trying to call the next a href, i needed to call the next list!
DEMO: http://so.devilmaycode.it/jquery-and-selecting-the-next-list-items-objects
your Javascript Code should be:
$(function() {
$('#main-nav li').click(function(e) {
e.preventDefault();
$('#main-nav li ul').slideUp(500);
$(this).find('ul:not(:visible)').slideDown(500);
});
});
little bit of CSS
#main-nav li ul { display:none }
your HTML should look like this:
<ul id="main-nav">
<li>Nav main 1
<ul>
<li>sub 1</li>
<li>sub 2</li>
<li>sub 3</li>
<li>sub 4</li>
</ul>
</li>
<li>Nav main 2
<ul>
<li>sub 1</li>
<li>sub 2</li>
<li>sub 3</li>
<li>sub 4</li>
</ul>
</li>
</ul>
Sorry for the noobish question.
I've got a menu similar to this:
<div id="navigation">
<ul>
<li>menu item</li>
<li>menu item
<ul>
<li>sub menu item</li>
<li>sub menu item
<ul>
<li>sub sub menu item</li>
<li>sub sub menu item</li>
<li>sub sub menu item</li>
</ul>
</li>
<li>sub menu item</li>
<li>sub menu item</li>
</ul>
</li>
<li>menu item</li>
<li>menu item</li>
</ul>
</div>
I'm trying to change the class for the selected page. I'm part way there with this:
$(function(){
var path = location.pathname.substring(1);
if ( path ){
$('#navigation a[href$="' + path + '"]').parent().attr('class', 'selected');
}
});
Which changes the class on the parent li. Cool. But what I really want to do is change the class on top level li. In other words if a "sub sub menu item" is selected goes all the way up the tree and changes the very first li that contains that link.
Would appreciate any help at all.
Thanks,
Andy.
You can use .parents() and :last (since they're returned in the order found...top parent is last) when looking for the <li>, like this:
$('#navigation a[href$="' + path + '"]').parents('li:last').addClass('selected');
Also .addClass() is probably what you're after here :)
$('#navigation>ul>li:has(a[href$="' + path + '"])')
use >
$('#navigation > ul > li > a[href$="' + path + '"]')