Check whether a li element has any children with value using jQuery - javascript

I need to check if the each li element has any value or not using jQuery. I am providing my code below.
$("#navbarNavDropdown ul a").each(function() {
if ($(this).find('li').has("ul").length) {
alert('Yeah, we have a ul ' + $(this).text());
} else {
alert('Yeah, we dont have a ul ' + $(this).text());
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navbar-toggleable-sm collapse navbar-collapse justify-content-end" id="navbarNavDropdown">
<ul>
<li>Level 1
<ul>
<li>Level 2<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
<ul class="dropdown-menu s-drop">
<li>Jacksonville</li>
</ul>
</li>
</ul>
</li>
<li class="dropdown mega-drop pstatic">
Admissions<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
</li>
</ul>
</div>
My requirement is: suppose inside the loop 1st li element has some children(ul) value here I want to print the text and 2nd li element has no children(ul) so it will come under else part. If also check the submenu(i.e-Level 2) has any ul value or not. My code is not working as expected.

This code will work you fine.
$("#navbarNavDropdown ul a").each(function() {
if ($(this).closest('li').has("ul").length) {
alert('Yeah, we have a ul ' + $(this).text());
} else {
alert('Yeah, we dont have a ul ' + $(this).text());
$(this).find('span').remove(); //to remove the span
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navbar-toggleable-sm collapse navbar-collapse justify-content-end" id="navbarNavDropdown">
<ul>
<li>Level 1
<ul>
<li>Level 2<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
<ul class="dropdown-menu s-drop">
<li>Jacksonville</li>
</ul>
</li>
</ul>
</li>
<li class="dropdown mega-drop pstatic">
Admissions<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
</li>
</ul>
</div>
But as per me, there is a better piece of code for your requirement
$("#navbarNavDropdown > ul > li").each(function() {
if ($(this).has("ul").length) {
alert('Yeah, we have a ul ' + $(this).text());
} else {
alert('Yeah, we dont have a ul ' + $(this).text());
$(this).find('span').remove(); //to remove the span
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navbar-toggleable-sm collapse navbar-collapse justify-content-end" id="navbarNavDropdown">
<ul>
<li>Level 1
<ul>
<li>Level 2<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
<ul class="dropdown-menu s-drop">
<li>Jacksonville</li>
</ul>
</li>
</ul>
</li>
<li class="dropdown mega-drop pstatic">
Admissions<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
</li>
</ul>
</div>
I have changed the #navbarNavDropdown ul a to #navbarNavDropdown>ul>li so it will only loop 2 times [saving the time and only looping first level elements removing the span] and as per your comment, I think this is the code you looking for.
I hope this solves your Bug.

This will solve your problem.
$("#navbarNavDropdown ul li").each(function() {
if ($(this).find("ul").length) {
alert('Yeah, we have a ul ' + $(this).text());
} else {
alert('No, we dont have a ul ' + $(this).text());
$(this).find('span').remove();
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navbar-toggleable-sm collapse navbar-collapse justify-content-end" id="navbarNavDropdown">
<ul>
<li>Level 1
<ul>
<li>Level 2<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
<ul class="dropdown-menu s-drop">
<li>Jacksonville</li>
</ul>
</li>
</ul>
</li>
<li class="dropdown mega-drop pstatic">
Admissions<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
</li>
</ul>
</div>

The <a> elements do not have any child <ul> or <li> elements. The one <ul> is a sibling not a child.
If you meant it to be a child you need to change your html so that the closing </a> is after the closing </ul>. Note though since you have child <a> elements you won't be able to wrap the whole thing in the anchor as that is invalid html and the browser will not create such a structure.
You need to change your line to something that checks for siblings like:
$(this).next('ul').find('li ul').length
//Or go back up to the parent element and then go searching back down
$(this).parent().find('li ul').length

ul is not inside a element, so $(this).find('li').has("ul") couldn't work.
use $(this).next() get ul element.

An alternative.
$("#navbarNavDropdown ul").each(function() {
$.each(this.children, function(index, element) {
const text = element.innerText.split('\n').reverse()[0];
if (element.localName === 'li' && $(element).has('ul').length > 0) {
alert('Yeah, we have a ul ' + text);
} else {
alert('Yeah, we dont have a ul ' + text);
$(element).find('span').remove();
}
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="navbar-toggleable-sm collapse navbar-collapse justify-content-end" id="navbarNavDropdown">
<ul>
<li>Level 1
<ul>
<li>Level 2<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
<ul class="dropdown-menu s-drop">
<li>Jacksonville</li>
</ul>
</li>
</ul>
</li>
<li class="dropdown mega-drop pstatic">
Admissions<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
</li>
</ul>
</div>

Related

Accordion only toggle first item

I have the code below in my index.php, only the first item in the accordion shows.
For instance: when I click on Status or Repeated, am expecting the sub-menu of the clicked item but instead I get the result from the first list. That is Position.
<style>
ul .sub_main{
cursor: pointer;
}
.nested {
display: none;
}
.active {
display: block;
}
</style>
<ul class="sidebar-menu" data-widget="tree">
<li class="header">MANAGE</li>
<li class="sub_main"><i class="fa fa-users"></i><span>Positions</span><i class="fa fa-plus" aria-hidden="true"></i>
<ul class="nested">
<li class=""><i class="fa fa-users"></i> <span>a link 1</span></li>
<li class=""><i class="fa fa-users"></i> <span>a link 2</span></li>
</ul>
</li>
<li class="sub_main"><i class="fa fa-tasks"></i> <span>Status</span><i class="fa fa-plus" aria-hidden="true"></i>
<ul class="nested">
<li class=""><i class="fa fa-tasks"></i> <span>b link 1</span></li>
<li class=""><i class="fa fa-tasks"></i> <span>b link 2</span></li>
<li class=""><i class="fa fa-tasks"></i> <span>b link 3</span></li>
</ul>
</li>
<li class="sub_main"><i class="fa fa-tasks"></i> <span>Repeated</span><i class="fa fa-plus" aria-hidden="true"></i>
<ul class="nested">
<li class=""><i class="fa fa-tasks"></i> <span>c link 1</span></li>
<li class=""><i class="fa fa-tasks"></i> <span>c link 2</span></li>
</ul>
</li>
</ul>
this is the script to show the accordion item when clicked.
var toggler = document.getElementsByClassName("sub_main");
var i;
for (i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click", function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
});
}
Your JS line with the class toggle method is being called on the parent of the "sub-main" class. This means that the querySelector is grabbing the first ".nested" element it finds from your ul.sidebar-menu element, which will always be the top ".nested" group.
If you simply remove the "parentElement" from that JS line, then the querySelector will look for the first ".nested" within the ".sub-main" (this) element.
Your JS should look like:
var toggler = document.getElementsByClassName("sub_main");
var i;
for (i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click", function() {
this.querySelector(".nested").classList.toggle("active");
});
}

Getting values from a <ul>, <li> tree format

I've the folloing tree view:
ul {
list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" />
<ul id="myTreeSelector" onClick="getPath()">
<li>
<span class="caret folder-selector"><i class="fa fa-folder"></i> first_folder</span>
<ul class="nested">
<li class="file"><i class="fa fa-file"></i> app1.dat</li>
<li class="file"><i class="fa fa-file"></i> app2.dat</li>
<li>
<span class="caret folder-selector"><i class="fa fa-folder"></i> second_folder</span>
<ul class="nested">
<li class="file"><i class="fa fa-file"></i> ret.dat</li>
</ul>
</li>
</ul>
</li>
</ul>
Which generates a folder tree like this:
What I'm loking for is that when I click on any file or folder, get the "full file/folder path". This means:
If I click in app1.dat, my desired output is: first_folder/app1.dat
If I click in second_folder, my desired output is: first_folder/second_folder
If I click in ret.dat, my desired output is: first_folder/second_folder/ret.dat
How can I archieve this? I tried with no luck to get the value:
function getPath() {
var value = $("#myTreeSelector").val()
console.log(value)
}
EDIT: The tree can have more than 2 levels, this is just a minified example.
Here is generic code, all you need to do is add event to li (using event delegation) and use parents to the li elements that are parents of selected li element.
$(function() {
$('#myTreeSelector').on('click', 'li', function() {
var item = $(this);
var path = [];
if (item.is('.file')) {
path.push(item.text().trim());
} else {
path.push(item.find('> .folder-selector').text().trim() + '/');
}
var parents = item.parents('#myTreeSelector li');
path = parents.map(function() {
return $(this).find('> .folder-selector').text().trim();
}).get().reverse().concat(path);
console.log(path.join('/'));
return false;
});
});
ul {
list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" />
<ul id="myTreeSelector">
<li>
<span class="caret folder-selector"><i class="fa fa-folder"></i> first_folder</span>
<ul class="nested">
<li class="file"><i class="fa fa-file"></i> app1.dat</li>
<li class="file"><i class="fa fa-file"></i> app2.dat</li>
<li>
<span class="caret folder-selector"><i class="fa fa-folder"></i> second_folder</span>
<ul class="nested">
<li class="file"><i class="fa fa-file"></i> ret.dat</li>
<li><span class="caret folder-selector"><i class="fa fa-folder"></i> third_folder</span></li>
</ul>
</li>
</ul>
</li>
</ul>

How to remove span tag if list has no value using Jquery

I need one help. I have many menu-submenu list in dropdown manner using Bootstrap. Here I need to remove the span tag if any list or sublist has no value inside it dynamically. I am explaining my code below.
<div class="navbar-toggleable-sm collapse navbar-collapse justify-content-end" id="navbarNavDropdown">
<ul id="ctl00_CPNavigation_ctl00_C_TA057AC37001_ctl00_ctl00_navigationUl" class="navbar-nav navbar-top-view nav">
<li class="dropdown mega-drop pstatic">
Programs<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
<ul class="dropdown-menu mega-h-drop-menu fwidth activeul">
<li class="dropdown">
Business
<ul class="dropdown-menu s-drop">
<li>Business Office Administration</li>
</ul>
</li>
<li class="dropdown">
Cosmetology
<ul class="dropdown-menu s-drop">
<li>Cosmetology</li>
</ul>
</li>
<li class="pstatic">
Health Care & Administration
<ul class="dropdown-menu mega-v-drop-menu w-100">
<div class="row fullmenu">
<div class="col-sm-6 pull-left">
<ul>
<li>Limited Scope X-Ray Technician</li>
<li>Patient Care Technician</li>
<li>Pharmacy Technician</li>
<li>Health Services Administration</li>
</ul>
</div>
<div class="col-sm-6 pull-left">
<ul>
<li>Medical Assistant Technician</li>
<li>Medical Front Office & Billing</li>
<li>Dental Assistant</li>
</ul>
</div>
</div>
</ul>
</li>
<li class="dropdown">
HVAC
<ul class="dropdown-menu s-drop">
<li>Heating Ventilation and Air Condition (HVAC)</li>
</ul>
</li>
<li class="dropdown">
Information Technology
<ul class="dropdown-menu s-drop">
<li>Information Technology</li>
<li>Computer Network Technician</li>
</ul>
</li>
<li class="dropdown">
Nursing
<ul class="dropdown-menu s-drop">
<li>Nursing</li>
</ul>
</li>
</ul>
</li>
<li class="dropdown mega-drop pstatic">
Campuses<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
<ul class="dropdown-menu mega-h-drop-menu activeul">
<li>Houston</li>
<li>Orlando</li>
<li>Boynton Beach</li>
<li class="dropdown">
More
<ul class="dropdown-menu s-drop">
<li>Jacksonville</li>
<li>Hialeah</li>
<li>Tampa</li>
<li>Lauderdale Lakes</li>
<li>Margate</li>
<li>Miami (Main Campus)</li>
<li>Pembroke Pines</li>
<li>West Palm Beach</li>
</ul>
</li>
</ul>
</li>
<li class="dropdown mega-drop pstatic">
Admissions<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
</li>
<li class="dropdown mega-drop pstatic">
Financial Aid<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
</li>
<li class="dropdown mega-drop pstatic">
Career Services<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
<ul id="ctl00_CPNavigation_ctl00_C_TA057AC37001_ctl00_ctl00_ctl02_ctl04_childNodesContainer" class="dropdown-menu activeul">
<li class="dropdown mega-drop pstatic">
Employer Resources<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
</li>
</ul>
</li>
<li class="dropdown mega-drop pstatic">
About Us<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
<ul id="ctl00_CPNavigation_ctl00_C_TA057AC37001_ctl00_ctl00_ctl02_ctl05_childNodesContainer" class="dropdown-menu activeul">
<li class="dropdown mega-drop pstatic">
Accreditations<span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span>
</li>
</ul>
</li>
</ul>
</div>
The above code is the html generated output. Actually all data are dynamically bind over the li element. Here I need if any parent li or child li has no ul element or value then I will remove the respective span class="caret" data-toggle="dropdown"><i class="fa fa-caret-down" aria-hidden="true"></i></span> tag. I need to make dynamically using Jquery/Javascript.
You can get it using jQuery:
$(".navbar-toggleable-sm span").each(function() {
if ($(this).parents("li:first").find("ul").length == 0)
$(this).hide();
else
$(this).show();
});
For each span found, check if its parent li has a child ul. If found, the span must be visible, otherwise should be hidden.

How to slide down just one level of element 's children, not sub-level

When I use this code:
jQuery:
$(this).next().slideDown()
of a selector :$(this).next()
HTML:
<li class="sub-menu two-level-collapse">
<a href="javascript:void(0);" class="two-level-collapse parent"><i
class="fa fa-line-chart"></i><span>Quản lý dữ liệu trạm</span><i
class="arrow fa fa-angle-right pull-right"></i></a>
<ul class="two-level-collapse">
<li class="sub-menu two-level-collapse">
<a class="two-level-collapse" id="sub-sub-a" href="javascript:void(0);">
<i></i><span>cem</span><i class="arrow fa fa-angle-right pull-right"></i></a>
<ul class="two-level-collapse">
<li class="two-level-collapse"><a
href='{{pathFor route='manager.csv' query='type=humid_cem'}}'>humid_cem</a></li>
<li class="two-level-collapse"><a
href='{{pathFor route='manager.csv' query='type=temp_cem'}}'>temp_cem</a></li>
<li class="two-level-collapse"><a href='{{pathFor route='manager.csv'
query='type=rainfall_cem'}}'>rainfall_cem</a>
</li>
</ul>
</li>
<li class="sub-menu two-level-collapse">
<a class="two-level-collapse" id="sub-sub-a" href="javascript:void(0);">
<i></i><span>kttvtw</span><i class="arrow fa fa-angle-right pull-right"></i></a>
<ul class="two-level-collapse">
<li class="two-level-collapse"><a href='{{pathFor route='manager.csv'
query='type=humid_kttvtw'}}'>humid_kttvtw</a>
</li>
<li class="two-level-collapse"><a
href='{{pathFor route='manager.csv' query='type=temp_kttvtw'}}'>temp_kttvtw</a>
</li>
<li class="two-level-collapse"><a
href='{{pathFor route='manager.csv' query='type=rainfall_kttvtw'}}'>rainfall_kttvtw</a>
</li>
</ul>
</li>
<li class="sub-menu two-level-collapse">
<a class="two-level-collapse" id="sub-sub-a" href="javascript:void(0);">
<i></i><span>global</span><i class="arrow fa fa-angle-right pull-right"></i></a>
</li>
</ul>
</li>
It expands all sub-level of $(this).next()
Like that: demo
How can I slide down just one level of element 's children, not sub-levels?
Thank you in advanced!
ahh.. now I get it.
is it that what you want?
https://www.w3schools.com/code/tryit.asp?filename=FMWU6SGV4H8C
basically i added that menu are initially hidden:
<style>
ul.two-level-collapse {
display:none
}
</style>
How can I slide down just one level of element 's children, not
sub-levels?
You mean only direct descendants should slide-down, then make it
$(this).next().find( "> ul.children" ).slideDown();
Demo
$( "a" ).click( function(e){
$(this).next().find( "> ul.children" ).slideToggle(); //using slideToggle since slideDown is not available with jquery.
e.preventDefault();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Clinical/Laboratory
<li class="page_item page-item-29 current_page_item parent">Clinical/Laboratory
<ul class="children" style="display: none;">
<li class="page_item page-item-40 parent">Histopathology
<ul class="children" style="display: none;">
<li class="page_item page-item-99">Test page</li>
</ul>
</li>
<li class="page_item page-item-42">Bacteriology</li>
<li class="page_item page-item-46">Packaging Guidelines</li>
<li class="page_item page-item-44">Water Quality Analysis</li>
</ul>
</li>
From Your question i understand that you want to get direct children on li element, if so you might use following line
$(this).next().firstElementChild
this will give you direct child on which you can use slideDown() method.

jQuery remove class on slideUp

I have a class applied to the "sub-menu-click" div when a sub menu is opened. When another sub menu is opened, the script closes the previous one but I need it to also remove the "sub-menu-open" class applied to the previous sub-menu-click but without removing the class to the new sub-menu opened.
$('.sub-menu-click').click(function(){
$(this).next(".sub-menu").slideToggle(250);
$(this).addClass("sub-menu-open");
$(this).parent().parent().children().children().not($(this)).next('.sub-menu').slideUp(250);
return false;
});
<ul id="nav">
<li>
Dashboard
</li>
<li>
<div class="sub-menu-click">Clients</div>
<ul class="sub-menu">
<li><i class="fa fa-angle-right"></i>Lookup Clients</li>
<li><i class="fa fa-angle-right"></i>Create a Client</li>
</ul>
</li>
<li>
<div class="sub-menu-click">Properties</div>
<ul class="sub-menu">
<li><i class="fa fa-angle-right"></i>Lookup Properties</li>
<li><i class="fa fa-angle-right"></i>Create a Property</li>
</ul>
</li>
<li>
<div class="sub-menu-click">Appointments</div>
<ul class="sub-menu">
<li><i class="fa fa-angle-right"></i>Lookup Appointments</li>
<li><i class="fa fa-angle-right"></i>Book an Appointment</li>
</ul>
</li>
<li>
<div class="sub-menu-click">Inventories</div>
<ul class="sub-menu">
<li><i class="fa fa-angle-right"></i>Lookup Inventories</li>
<li><i class="fa fa-angle-right"></i>Create an Inventory</li>
</ul>
</li>
<li>
<div class="sub-menu-click">Check-Ins</div>
<ul class="sub-menu">
<li><i class="fa fa-angle-right"></i>Lookup Check-Ins</li>
<li><i class="fa fa-angle-right"></i>Create a Check-In</li>
</ul>
</li>
<li>
<div class="sub-menu-click">Check-Outs</div>
<ul class="sub-menu">
<li><i class="fa fa-angle-right"></i>Lookup Check-Outs</li>
<li><i class="fa fa-angle-right"></i>Create a Check-Out</li>
</ul>
</li>
</ul>
Try this
$('.sub-menu-click').click(function(){
$(this).next('.sub-menu').slideToggle(250);
$(this).toggleClass('sub-menu-open');
});
It will toggle the class and the slide to achieve the result
Try this:
$('.sub-menu-click').click(function(){
$('.sub-menu-click').next(".sub-menu").slideUp(250);
$('.sub-menu-click').removeClass('sub-menu-click');
$(this).next(".sub-menu").slideToggle(250);
$(this).addClass("sub-menu-open");
});
$('.sub-menu-click').click(function(){
$("sub-menu-open").removeClass("sub-menu-open");
$(this).next(".sub-menu").slideToggle(250);
$(this).addClass("sub-menu-open");
$(this).parent().parent().children().children().not($(this)).next('.sub-menu').slideUp(250);
return false;
});

Categories

Resources