I'm a beginner programmer and I'm stuck with the following problem:
If I have a nested unordered list, how can I copy only the elements up
to a certain level? For example if I want to reduce this unordered list to the first two levels:
<ul>
<li>A</li>
<ul>
<li>C<br>
</li>
<li>D<br>
</li>
<ul>
<li>E<br>
</li>
<li>F<br>
</li>
<ul>
<li>G<br>
</li>
<li>H<br>
</li>
</ul>
</ul>
<li>E<br>
</li>
</ul>
<li>B</li>
</ul>
to
<ul>
<li>A</li>
<ul>
<li>C<br>
</li>
<li>D<br>
</li>
<li>E<br>
</li>
</ul>
<li>B</li>
</ul>
Is there any easy way to achieve this?
Simple version:
$('ul ul ul').remove();
jsFiddle Demo
I also wrote a little function that lets you specify a root element and a level also:
function reduce(root, selector, level) {
var use = root;
for (var i = 0; i <= level; i++) {
use += ' ' + selector;
}
$(use).remove();
}
Use by calling:
//if the lists are in an element with the id 'root', see Demo
reduce('#root', 'ul', 2);
jsFiddle Demo
This should be something like $('ul ul ul').remove(), but you'd better enclose it in for example div with id or class so you can do local purge $('div.twolvls ul ul ul').remove()
If you're simply removing 3rd level unordered lists, you could use $(ul ul ul).remove().
Related
Let's say my code looks like that
const menu = document.querySelector(".menu");
//now i need to select <a> tags with 'design' and 'development', but using menu element i've already selected.
//const firstLineChilds = menu.querySelector(???);
<ul class="menu">
<li>Design</li>
<li>Development</li>
<li>
<ul class="sub-menu">
<li>DevOps</li>
<li>Managment</li>
</ul>
</li>
</ul>
Is it even possible to to this the 'clean way'? Or i just need to use menu.parentNode.querySelector(".menu > li > a")
You can chain querySelector and other such methods and it will search children of previous returned node: document.querySelector(".menu").querySelectorAll("a") or menu.querySelectorAll("a")
Converting the hrefs to an Array (in the snippet the spread syntax is used for that) enables you to filter them:
const relevantHrefs = [...document.querySelectorAll(".menu li a")]
.filter(href => ["Design", "Development"].find(h => href.textContent === h));
console.log(relevantHrefs);
// based on comment, this is maybe what OP needs
const menu = [...document.querySelectorAll(".menu > li:nth-child(-n+2) a")];
console.log(menu);
<ul class="menu">
<li>Design</li>
<li>Development</li>
<li>
<ul class="sub-menu">
<li>DevOps</li>
<li>Managment</li>
</ul>
</li>
</ul>
Yes, you can use :scope in conjunction with child combinators, in menu.querySelectorAll():
const menu = document.querySelector(".menu")
const firstLineChilds = menu.querySelectorAll(":scope > li > a");
console.log(firstLineChilds);
<ul class="menu">
<li>Design</li>
<li>Development</li>
<li>
<ul class="sub-menu">
<li>DevOps</li>
<li>Managment</li>
</ul>
</li>
</ul>
If you use descendant combinators, you'll still get the nested a elements, which is not what you want. See What does the ">" (greater-than sign) CSS selector mean?
I am trying to construct a jquery statement that will slideUp() all <ul> elements whose siblings don't contain a set of specific classes (.clicked, .chosen).
Suppose I have the following nested <ul> structure:
<ul class="mainmenu">
<li>Dogs</li>
<ul>
<li>Fido</li>
<li class="chosen">Barney</li>
<li>Turbo</li>
</ul>
<li>Cats</li>
<ul>
<li>Sylvester</li>
<li>Felix</li>
<li>Garfield</li>
</ul>
<li class="clicked">Hamsters</li>
<ul>
<li>Chubbs</li>
<li>Oreo</li>
<li>Ruby</li>
</ul>
</ul>
For the above example, I would like to slideUp() only the 'Cats' <ul> element ('Sylvester', 'Felix', 'Garfield') because none of it's elements use the 'chosen' or 'clicked' classes.
My current jquery statement reads:
$('.mainmenu').first().siblings().not('.clicked, .chosen').slideUp();
This, and everything else I have tried, returns nothing. Suggestions?
You HTML looks challenging :) but somehow, I've managed to create a query to perform what you're looking for.
And if you want to check multiple class for particular element you can use is() as well.
//Check li doesn't have clicked class and then filter ul next to the li
$('.mainmenu > li').not('.clicked').next('ul').filter(function(){
//Find the ul, if it's any of li doesn't have chosen class
if(!$(this).find('li').hasClass('chosen'))
{
return $(this);
}
}).slideUp();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="mainmenu">
<li>Dogs</li>
<ul>
<li>Fido</li>
<li class="chosen">Barney</li>
<li>Turbo</li>
</ul>
<li>Cats</li>
<ul>
<li>Sylvester</li>
<li>Felix</li>
<li>Garfield</li>
</ul>
<li class="clicked">Hamsters</li>
<ul>
<li>Chubbs</li>
<li>Oreo</li>
<li>Ruby</li>
</ul>
</ul>
I am have a link in a li and when you click on it, it should open a ul, also contained in the li. I can't seem to get it to select the right element though. Code below
HTML
<ul>
<li>
hi
<ul>
<li class="hidden">more stuff</li>
</ul>
</li>
</ul>
CSS
.hidden{display:none;}
Js
$( "a" ).click(function() {
$(this).parent("li").children("ul").css("display","block");
});
Since the ul is the next sibling to the a, you'd use next to access it. Then you can look at the ul's children (children) or descendants (find) for the .hidden one and remove the class (removeClass):
$(this).next().children(".hidden").removeClass("hidden");
Live Example:
$("a").on("click", function() {
$(this).next().children(".hidden").removeClass("hidden");
return false;
});
.hidden {
display: none;
}
<ul>
<li>
one
<ul>
<li class="hidden">more stuff</li>
</ul>
</li>
<li>
two
<ul>
<li class="hidden">more stuff</li>
</ul>
</li>
<li>
three
<ul>
<li class="hidden">more stuff</li>
</ul>
</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
In your code you are trying to make ul displayed although it is visible and it does not effect the li under it so you need to access that li like this. Removing the hidden class of the element to make it displayed is a better approach than assigning inline style as the commentators said
$(this).parent("li").children("ul").children("li").removeClass("hidden");
check here fiddler link...
hope it will help you....
$( "a" ).click(function() {
$(this).next().children(".hidden").removeClass("hidden");
});
I have markup of ul and li. what I need to do is get text value from direct descentc li a text only. Expected result is a,b,c. fiddle
jquery
$(function(){
$('ul').first().find(' > li').each(function(){
alert($('a',this).text())
})
})
HTML
<ul>
<li><a>a</a>
<ul>
<li><a>a1</a></li>
<li><a>a2</a></li>
</ul>
</li>
<li><a>b</a></li>
<li><a>c</a></li>
</ul>
Use .children() instead which travels a single level down the DOM tree. Created a snippet for you:
$(function() {
$('ul').first().children('li').each(function() {
alert($(this).children('a').text())
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><a>a</a>
<ul>
<li><a>a1</a>
</li>
<li><a>a2</a>
</li>
</ul>
</li>
<li><a>b</a>
</li>
<li><a>c</a>
</li>
</ul>
I have a nested list:
<ul>
<li id="1">first</li>
<li id="2">second</li>
<ul>
<li id="2-1">second nested first element</li>
<li id="2-2">second nested secondelement</li>
<li id="2-3">second nested thirdelement</li>
<ul>
<li id="2-3-1">Other</li>
</ul>
</ul>
<li id="3"i>third</li>
<li id="4">fourth</li>
</ul>
Each element has an id that indicates the position within the list. How do I generate it automatically?
Thank you.
UPDATE:
html is generated by Apache velocity without ID. I'm trying to create a method for updating the id if you move elements with jquery sortable. The structure of the id must be "1" for the first item "1-1" for the first element of the first "li". I tried using index () but I can't generate the id in the form that I need
It's not clear what you exactly want to do here, but here's an example of generating dynamic li's with dynamic id's:
HTML:
<ul id="autoGenerated">
</ul>
JS:
for(var i = 1; i < 3 ;i++){
$("#autoGenerated").append("<li id=2-" + i + ">Testing " + i + "</li>")
}
$('#autoGenerated li').click(function(){
alert($(this).attr("id"));
})
Fiddle.