I have a set of li elements and I want to give all li elements below the ul container an extra class based on the .login class. The login element isn't a parent element but in the same container. Would this be possible with jQuery or vanilla js?
<ul class="submenu" id="sub0">
<li class="menugroup dcjq-parent-li">
<ul class="rightmenu login">
<li></li>
<li></li>
</ul>
</li>
<li></li> <-----new class
<li></li> <-----new class
<li></li> <-----new class
<li></li> <-----new class
<li></li> <-----new class
<li></li> <-----new class
</ul>
You can use the following code:
$("ul.login")
.parents("li")//get ancestor li element
.nextAll()//get all next li elements
.addClass("active");//add desire class
.active {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="submenu" id="sub0">
<li class="menugroup dcjq-parent-li">
<ul class="rightmenu login">
<li>
</li>
<li>
</li>
</ul>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
</ul>
References
.nextAll()
.addClass()
.parents()
Related
I am trying to get last li element of list . but it is not giving correct output. here is my markup
<div class="abc">
<ul>
<li>1</li>
<ul><li>1.1</li><li>1.2</li></ul>
<li>2</li>
<ul><li>2.1</li><li>2.2</li></ul>
<li>3</li>
<ul><li>3.1</li><li>3.2</li></ul>
</ul>
</div>
trying like this
console.log(document.querySelector('.abc ul li:last-child').innerHTML)
output Element
<li>1.2</li>
Expected output
<li>3</li>
There are 2 problems
Your HTML Is invalid as ul is not a valid child of ul so the nested ones need to be actually inside a li
Use the > modifier to find direct descendents only in the selector
console.log(document.querySelector('.abc>ul>li:last-child').innerHTML)
<div class="abc">
<ul>
<li>
1
<ul>
<li>1.1</li>
<li>1.2</li>
</ul>
</li>
<li>
2
<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>
3
<ul>
<li>3.1</li>
<li>3.2</li>
</ul>
</li>
</ul>
</div>
If you do just want the text (and not the nested ul) you could put that text in a span and select that only
console.log(document.querySelector('.abc>ul>li:last-child span').innerHTML)
<div class="abc">
<ul>
<li>
<span>1</span>
<ul>
<li>1.1</li>
<li>1.2</li>
</ul>
</li>
<li>
<span>2</span>
<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>
<span>3</span>
<ul>
<li>3.1</li>
<li>3.2</li>
</ul>
</li>
</ul>
</div>
If you do just want the text (and not the nested ul) you could put that text in a span and select that only
You can just go for the javascript way like this.
li = document.querySelectorAll('.abc>ul>li');
console.log(li[li.length-1].innerText);
console.log(document.querySelector('.abc ul li:last-child').innerHTML)
This syntax of giving white space instead of adjacent selectors like ">" is used when we want to apply common styles to multiple class.
So replacing your whitespace with adjacent selectors like > will work in your case to select all its descendent childs.
console.log(document.querySelector('.abc>ul>li:last-child').innerHTML)
<div class="abc">
<ul>
<li>
1
<ul>
<li>1.1</li>
<li>1.2</li>
</ul>
</li>
<li>
2
<ul>
<li>2.1</li>
<li>2.2</li>
</ul>
</li>
<li>
3
<ul>
<li>3.1</li>
<li>3.2</li>
</ul>
</li>
</ul>
</div>
How to remove link from parent menu anchor if it has submenus
<ul class="sitemap-ul">
<li> Home</li>
<li> about Us <!-- Remove link-->
<ul>
<li>mission</li>
<li>vission</li>
</ul>
</li>
<li> Media <!-- Remove link-->
<ul>
<li>news</li>
</ul>
</li>
<li> Contact</li>
</ul>
You can use jQuery :has() pseudo-class selector.
$('.sitemap-ul > li:has(ul) > a').remove()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="sitemap-ul">
<li> Home</li>
<li> about Us <!-- Remove link-->
<ul>
<li>mission</li>
<li>vission</li>
</ul>
</li>
<li> Media <!-- Remove link-->
<ul>
<li>news</li>
</ul>
</li>
<li> Contact</li>
</ul>
UPDATE : In case you just want to replace a tag with text then use contents() method with unwrap() method.
$('.sitemap-ul > li:has(ul) > a')
// get children element
.contents()
// unwrap them
.unwrap()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="sitemap-ul">
<li> Home</li>
<li> about Us
<!-- Remove link-->
<ul>
<li>mission</li>
<li>vission</li>
</ul>
</li>
<li> Media
<!-- Remove link-->
<ul>
<li>news</li>
</ul>
</li>
<li> Contact</li>
</ul>
Assuming you want to remove the <a> elements themselves but leave behind their text content you can use :has() to get the relevant li with submenus, then replaceWith() on the child a elements, like this:
$('.sitemap-ul > li:has(ul) > a').replaceWith(function() {
return $(this).text();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="sitemap-ul">
<li>Home</li>
<li>
About Us
<ul>
<li>mission</li>
<li>vission</li>
</ul>
</li>
<li>
Media
<ul>
<li>news</li>
</ul>
</li>
<li>Contact</li>
</ul>
$('.sitemap-ul > li').each(function(){
if($('ul', this).length > 0){
$(this).closest("a").click(function(e){
e.preventDefault();
});
}
});
I have a solution by using vanilla js for you.
var elements = document.querySelectorAll(".sitemap-ul li")
Array.from(elements).forEach(function(el) {
if (el.children.length > 1) {
el.removeChild(el.children[0])
}
});
I'm trying to select theses elements with JQuery :
<div attribute="distinct-value"> <!-- i only want links in this one, select based on the attribute -->
<div>
<div>
<div class="col1">
<ul>
<li>
<!-- i want this -->
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</li>
</ul>
<ul>
<li>
<!-- and this... -->
<ul>
<li></li>
</ul>
</li>
</ul>
</div>
<div class="col2">
<ul>
<li>
<!-- and this... -->
<ul>
<li></li>
<li></li>
</ul>
</li>
</ul>
<ul>
<li>
<!-- and this... -->
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</li>
</ul>
</div>
<!-- col3, col4, etc, etc... -->
</div>
</div>
</div>
<div attribute="another-distinct-value">
<!-- same content structure has 'distinct-value div' -->
</div>
<div attribute="another-other-distinct-value">
<!-- same content structure has 'distinct-value div' -->
</div>
I want the first link in the first li of every ul markups that are not inside a li, for every div that has a "col" class. I hope everything is clear..
Can someone help me out ?
Loop through your elements like so
$('div[attribute="distinct-value"] [class^=col] li:has(ul) > a').each(function(index) {
console.log( index + ": " + $( this ).text() );
});
console.log($('div[class^=col] > ul > li > a'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div attribute="distinct-value">
<div>
<div>
<div class="col1">
<ul>
<li>
<!-- i want this -->
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</li>
</ul>
<ul>
<li>
<!-- and this... -->
<ul>
<li></li>
</ul>
</li>
</ul>
</div>
<div class="col2">
<ul>
<li>
<!-- and this... -->
<ul>
<li></li>
<li></li>
</ul>
</li>
</ul>
<ul>
<li>
<!-- and this... -->
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</li>
</ul>
</div>
<!-- col3, col4, etc, etc... -->
</div>
</div>
</div>
You can target li that has ul in it along with immediate child selector(>) to target immediate child anchor element:
$('[class^=col] li:has(ul) > a');
You can iterate over above set of elements and perform the task. If you want to get all the hrefs of anchor element, you need to use .map() with .get():
var allhref = $('[class^=col] li:has(ul) > a').map(function(){
return $(this).attr('href');
}).get();
var allhref = $('[class^=col] li:has(ul) > a').map(function(){
return $(this).attr('href');
}).get();
alert(allhref);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div attribute="distinct-value">
<div>
<div>
<div class="col1">
<ul>
<li>
<!-- i want this -->
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</li>
</ul>
<ul>
<li>
<!-- and this... -->
<ul>
<li></li>
</ul>
</li>
</ul>
</div>
<div class="col2">
<ul>
<li>
<!-- and this... -->
<ul>
<li></li>
<li></li>
</ul>
</li>
</ul>
<ul>
<li>
<!-- and this... -->
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</li>
</ul>
</div>
<!-- col3, col4, etc, etc... -->
</div>
</div>
</div>
Try this:
$('div[class^=col] > ul > li > a').each(function() {
doSomething( $(this) );
});
I got this HTML:
<ul>
<li>Test</li>
<li>Test2</li>
<a href="#" class="with-sub"><li>Test3</li>
<ul class="sub">
<li>Sub1</li>
<li>Sub2</li>
<li>Sub3</li>
</ul>
</a>
</ul>
And jQuery:
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
$( document ).ready(function() {
$(".sub").hide();
});
$(".with-sub").click(function() {
$(this).find(".sub").slideDown( "slow", function() {
});
});
</script>
When I click on the link with "with-sub" class nothing happens.
You can change your html and jquery to following:
$(".with-sub").click(function() {
$(this).next("ul").slideDown();
});
.sub {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<a href="#">
<li>Test</li>
</a>
<a href="#">
<li>Test2</li>
</a>
<a href="#" class="with-sub">
<li>Test3
<ul class="sub">
<li>Sub1
</li>
<li>Sub2
</li>
<li>Sub3
</li>
</ul>
</li>
</a>
</ul>
As mention in comments your html is not correct. ul elements can contain zero or more li elements, eventually mixed with ol and ul elements.
$(".with-sub").click(function() {
$(this).find("ul").toggle();
});
.sub {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
Test
</li>
<li>
Test2
</li>
<li class="with-sub">Test3
<ul class="sub">
<li>
Sub1
</li>
<li>
Sub2
</li>
<li>
Sub3
</li>
</ul>
</li>
</ul>
Your current code does not work because you are attempting to bind an event to elements that do not exist in the DOM yet - you need to put the click() handler inside the DOMReady handler.
Also note that your HTML is invalid - only li elements can be direct descendants of the ul element. Try this:
<ul>
<li>
Test
</li>
<li>
Test2
</li>
<li>
Test3
<ul class="sub">
<li>
Sub1
</li>
<li>
Sub2
</li>
<li>
Sub3
</li>
</ul>
</li>
</ul>
Once you've fixed your HTML, the following jQuery will work:
$(document).ready(function() {
$(".sub").hide();
$(".with-sub").click(function() {
$(this).siblings(".sub").slideDown("slow");
});
});
Working example
<ul>
<li>
<ul></ul>
</li>
<li></li>
<li></li>
<li></li>
<li>
<ul></ul>
</li>
</ul>
How do I add class="parent" only for li, which has ul inside it?
You can use :has() in your selector, like this:
$("li:has(ul)").addClass("parent")