collapsing a list using jquery - javascript

I have a list I am trying to collapse and am having trouble once I get lower in the hierarchy. Here is my html:
<ul class="list">
<li>
<a>Categories</a>
<ul>
<li>
<a>Parent</a>
<ul>
<li><a>Child</a></li>
<li><a>Child</a></li>
<li><a>Child</a></li>
</ul>
</li>
<li>
<a>Parent</a>
<ul>
<li><a>Child</a></li>
<li><a>Child</a></li>
<li><a>Child</a></li>
</ul>
</li>
<li>
<a>Parent</a>
<ul>
<li><a>Child</a></li>
<li><a>Child</a></li>
<li><a>Child</a></li>
</ul>
</li>
<li>
<a>Parent</a>
<ul>
<li><a>Child</a></li>
<li><a>Child</a></li>
<li><a>Child</a></li>
</ul>
</li>
</ul>
</li>
</ul>
Heres my jquery
$( document ).ready(function() {
$('.list > li a').click(function(){
$(this).parent().find('ul').toggle();
});
});
And here is a jfiddle: http://jsfiddle.net/u7bczqup/
Once you click on Categories the Parents come down. When this happens, all the children of the parents are shown and not hidden. Why are these ones not hidden? Ive tried adjusting my jquery but that causes it to not work at all.

They are not hidden because jquery find searches any descendants below it and then you are toggling them, you should use children().
Try this:
$(this).parent().children('ul').toggle();
http://jsfiddle.net/u7bczqup/1/
https://api.jquery.com/children/

Give this a shot.
JS:
$( document ).ready(function() {
$('.list > li a').click(function(){
$(this).next('ul').toggle();
});
});
The issue with using .find() is that it is finding all the ul element. You can check this by adding this line: console.log($(this).parent().find('ul')); This will print all the ul tags it is "finding" to the console. Because it is finding all of them, it is toggling all of them.

You're searching for all unordered list elements in the method .find('ul') that are direct descendants.
It should be .find('ul:first-child') ore more precisely .children(ul:first) so it would be
$( document ).ready(function() {
$('.list > li a').click(function(){
$(this).parent().children('ul').toggle();
});
});
for more refer to jquery find method

Related

How to find only first entry in dom

I have some dom like
.....
<ul>*
<li>
<ul>
Sone html here
</ul>
</li>
</ul>
.....
<ul>*
<li>
<ul>
<li>
<ul>
Some html here
</ul>
</li>
</ul>
</li>
</ul>
......
How can I find the first <ul> elements (marked by *) using jQuery?
I used something like
$('body ul:first-child')
but this returns only one element
You need to use immediate child selector to target elements that are immediate child of their parent:
$('body > ul')
I don't know why few person recomended to delete answer bnu right answer is
$('ul:not(ul ul)')
we need to exclude ul included in ul in this case we get ul only on top level (marked by *)

Add/Remove class "current" to li in nav

I have a navigation bar in which I want to add a class to the li tag of the current page so that I can add css to show what page you are on. I have attempted it using this script:
<script>
$(function() {
$("#nav.ul.li").click(function() {
$("#nav.ul.li").removeClass("current");
$(this).addClass("current");
});
});
</script>
This is the html I am using for my navbar:
<nav id="nav">
<ul>
<li>Home</li>
<li>
Events Calender
<ul>
<li>Rules</li>
<li>Facilities</li>
</ul>
</li>
<li>Video Guides</li>
<li>Gallery</li>
<li>Store</li>
<li>Where to find us</li>
<li>Contact Us</li>
<li>About Us</li>
</ul>
</nav>
However this script didn't work, so using javascript/jquery what is the best way to set a class on click to the li tags in my navigation bar?
All help much appreciated!
Remove the dots used like in #nav.ul.li and put space between them:
$(function() {
$("#nav ul li").click(function() {//or #nav > ul > li for direct element
$("#nav ul li").removeClass("current");
$(this).addClass("current");
});
});
Use . when you have a class on them like $('.sel') for <div class="sel"> and use # for element which has id as you normally use in css.
Use $("#nav > ul > li") instead of $("#nav.ul.li"). jQuery selector uses the same syntax as CSS. Other solution like $("#nav ul li") will also add/remove classes in unordered list puttes inside one of your <li> elements.

addClass/removeClass on HTML menu isn't working

i've got a problem with getting my navigation bar to work. This probably is very easy to solve but i've been trying things for ages and can't get it to work. For CSS purposes i want the list item in the nav bar to get the class 'selected' when clicked and removed when a different nav bar item is clicked. For some reason it doesn't work. i'll show the code here:
<script type="text/javascript">
$('ul.navigation li a').click(function(){
$('ul.navigation li a').removeClass('selected');
$(this).addClass('selected');
});
</script>
I put this part in the <head>...</head>
This is the navigation bar which it's not having any effect on:
<div id="menuWrapper">
<nav>
<ul class="navigation underlinemenu" id="gooeymenu">
<li id="home" class="selected">Home</li>
<li id="work">Work</li>
<li id="services">Services</li>
<li id="about">About me</li>
<li id="contact">Contact</li>
</ul>
</nav>
</div>
Now when i go to the browser and inspect the element it doesn't show any indication of adding the class 'selected' to the clicked menu item. When i check the console it gives some sort of error about the $('ul.navigation li a').click(function(){ part of the javascript saying it isn't a function.
I hope this has explained my problem, i still think it's probably easy to solve but i've been stuck on this for an entire day so i hope anyone here can help me.
Always wire up your events within a .ready() function.
If you apply the .ready function to the document, you ensure that your events are wired up. Read here for a brief introduction on using $(document).ready()
//Wait for the DOM to load and be ready:
$(document).ready(function() {
$('ul.navigation li a').click(function(){
//Find the navigation link that is actually with the 'selected' class.
$('ul.navigation li.selected').removeClass('selected');
$(this).parent().addClass('selected');
});
});
The element you are adding the 'selected' class doesn't look right.
In your html markup, you have the <li class='selected'><a href=''> but in your javascript you are removing and adding the selected class on the a element.
So you want to do something like:
$(document).ready(function() {
$('ul.navigation li a').click(function(){
$('ul.navigation li.selected').removeClass('selected');
$(this).parent().addClass('selected');
});
});
Unless you meant to have the class on the a element, then just your initial HTML was wrong, and then Sergio's solution would work.
Here you have the "selected" class in the "LI" element
<ul class="navigation underlinemenu" id="gooeymenu">
<li id="home" class="selected">Home</li>
<li id="work">Work</li>
<li id="services">Services</li>
<li id="about">About me</li>
<li id="contact">Contact</li>
</ul>
but in your javascript you are removing and adding the "selected" class on the "A" element
So try this:
$(document).ready(function() {
$('ul.navigation li a').click(function(){
$('ul.navigation li').removeClass('selected');
$(this).parent().addClass('selected');
});
});

How can I stop a JavaScript function from affecting a child element?

I have looked around for a solution to this problem, but it's so wonky that I doubt many people have considered it. A web application that I've recently inherited as a web administrator runs on Drupal (version 6). Unfortunately, I am unable to edit the Drupal install or create a custom theme until May due to other obligations that must be tended to first.
First off, I realize and whole-heartedly agree that there are more efficient (and elegant) ways of solving this problem, but for the time being, this is what the client wants and is comfortable with implementing.
Anyways, the old administrator was using Drupal to develop the site's navigation. The code that Drupal spits out on the HTML page is:
<ul class="menu">
<li class="expanded first">Housing
<ul class="menu">
<li class="leaf first">Housing Roster</li>
<li class="leaf">My Floor</li>
<li class="leaf">Photo Viewer</li>
<li class="leaf last">Building Maintenance</li>
</ul>
</li>
<li class="expanded">Reports
<ul class="menu">
<li class="leaf first">Build Floor Report</li>
<li class="leaf">Submit Incident Report</li>
<li class="leaf last">Submit Lockout</li>
</ul>
</li>
<li class="expanded">Office
<ul class="menu">
<li class="leaf first">Check In Package</li>
<li class="leaf">Check Out Building Package</li>
<li class="leaf">Check Out Campus Package</li>
<li class="leaf last">Check Equipment Out</li>
</ul>
</li>
<li class="expanded">Staff
<ul class="menu">
<li class="leaf first">Pre Programs</li>
<li class="leaf">Post Program</li>
<li class="leaf">Programming Database</li>
<li class="leaf last">Staff Downloads</li>
</ul>
</li>
<li class="leaf">My account</li>
<li class="leaf last">Log out</li>
The biggest concern I have with this output is that there is a ul element with the class attribute of "menu" nested inside of another ul element with the class attribute of "menu."
The goal of the JavaScript function that I am writing is to
Allow for jQuery to expand and collapse the child ul element whenever the respective li element with a class of "expanded" is clicked
Change the href attribute of ONLY the li elements with a class of "expanded" to "javascript:void(null)" so that they don't redirect the user to any page
Here is the JavaScript function that I've got going so far:
<script type="text/javascript">
$(function() {
//Hide the nested lists
$('ul.menu li.expanded ul.menu').hide();
//Change the destination of the header links
$('ul.menu li.expanded a').attr("href", "javascript:void(null)");
//Toggle the display of the nested lists
$('ul.menu li.expanded a').click(function() {
$(this).next().slideToggle('normal');
});
});
</script>
This works just fine, except it changes the href attribute of the nested li elements to "javascript:void(null)" as well. Is there a way that I can alter my JavaScript function to make sure that it applies the new href attribute ONLY to the li elements with a class of "expanded" and not to the li elements with a class of "leaf?"
At this point, I'm really only interested in an alteration of my JavaScript function. Like I said, I know and agree that there are better methods (such as altering the html output of the Drupal theme to begin with), but if I can get a quick fix in as a temporary solution while I rebuild the entire application, that would be awesome!
Please let me know if you have any suggestions!!!
THANKS!!!
Use a more specific selector:
$('ul.menu > li.expanded > a').attr( ...
The > matches only immediate children instead of all children.
If you're just trying to prevent the browser from following the href, you don't need the "javascript:void(null)". What you want to do instead is to stop the event from propagating:
$("ul.menu li.expanded > a").click(function(event) {
event.stopPropagation();
...
});
You could try
$('ul.menu li.expanded>ul.menu').hide();
This makes it apply only to the next element.
Another way would be to use
$('ul.menu li.expanded ul.menu:first').hide();
You can use the direct child selector ">".
e.g:
<script type="text/javascript">
$(function() {
//Hide the nested lists
$('ul.menu li.expanded ul.menu').hide();
//Change the destination of the header links
$('ul.menu li.expanded > a').attr("href", "javascript:void(null)");
//Toggle the display of the nested lists
$('ul.menu li.expanded > a').click(function() {
$(this).next().slideToggle('normal');
});
});
</script>

jQuery Accordion

Just wondering if anyone can provide some basic advice on an accordion I'm trying to simplify. Got a working version, but it seems way overly complex. Here is my new JS.
$(document).ready(function() {
$("#themes li ul").hide();
$("#themes li").hover(function() {
$("ul").show();
}, function() {
$("li ul").hide();
});
The markup looks like this:
<ul>
<li>Tier 1
<ul>
<li>Tier 2</li>
<li>Tier 2</li>
</ul>
</li>
<li>Tier 1
<ul>
<li>Tier 2</li>
<li>Tier 2</li>
</ul>
</li>
</ul>
My script works alright. But it shows all of the child ul's when any parent li is hovered, and it hides all the child ul's when unhovered. Just not sure how I can get it to A.) Only .show the li > ul when that specific li is hovered. And B.) Hide the shown li > ul only when another one is hovered (not itself). Example + explanation would be especially helpful! Thanks!!
Why can't you use the JQuery UI Accordion. This will solve your problem. The js is and the html is very simple here
<div id="accordion">
<h3>First header</h3>
<div>First content</div>
<h3>Second header</h3>
<div>Second content</div>
</div>
jQuery(document).ready(function(){
$('#accordion').accordion();
});
EDITED
The issue with your code is it hides and displays all the 'ul' components inside any 'li' components on hover of any one li. Here is the code to solve this issue, this will hide/show the 'ul' which comes inside the current 'li'
$(document).ready(function() {
$("#themes li ul").hide();
$("#themes li").hover(function() {
$(this).find("ul").show();
}, function() {
$(this).find("ul").hide();
});
});

Categories