I have a list structure that looks as follows:
<ul id="BirdMother" class="parent">
<ul class="child">
<li class="baby">
</ul>
<ul class="child">
<li class="baby">
</ul>
<ul class="child">
<li class="baby">
</ul>
</ul>
I want to select all the baby list items in an iterative manner to use in a function that looks like this: function feedBabies(babyList).
How can I select all the baby items?
Edit: What if there are multiple baby items in the page and I only want the babies from a certain parent list. Eg: Only Bird babies. (Edited the code above).
Just use class selector
var babyList = $(".baby");
feedBabies(babyList);
For certain parent
var babyList = $("#BirdMother .baby");
feedBabies(babyList);
Here you have solution
$("#useThisList > ul").each(function(){
alert($(this).html());//this will give you html
alert($(this).text());// this will give you text in li
});
Related
I need to loop through the DOM with JQuery, and add a click handler to multiple parent elements that contain a child that will also be given a slideToggle(). I have the logic working fine when I add the click handlers manually, but now I need to be able to dynamically do this to multiple parent elements.
Here is my HTML:
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
Basically, you click on .sub-menu-link to slideToggle() .sub-menu-list.
Here is the JS that I have working so far. It targets the id's manually currently, which feels gross:
$('#sub-menu-link-1').click(function() {
$('#sub-menu-list-1').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
$('#sub-menu-link-2').click(function() {
$('#sub-menu-list-2').slideToggle(100);
$(this).toggleClass('active-menu-link');
});
My apologies if this is something very apparent to do in JQuery. I am not at all familiar with it, and it just so happens to be a requirement of this project.
you could simply use below code.
select all list items with class name and add listener. click will be attached to all elements
$('.sub-menu-link').click(function() {
$(this).slideToggle(100);
$(this).toggleClass('active-menu-link');
});
You already have classes, so just use them instead of the ids: use this to refer to the clicked element, .next() to get the next sibling (the li.sub-menu), and .find('.sub-menu-list') to get to the ul you want to toggle:
$('.sub-menu-link').click(function() {
const $subMenuList = $(this).next().find('.sub-menu-list');
console.log($subMenuList.text().trim());
$subMenuList.slideToggle(100);
$(this).toggleClass('active-menu-link');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="map-poi-nav">
<ul class="map-poi-nav-dropdown">
//Parent #1
<li class="sub-menu-link" id="sub-menu-link-1">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Activities
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-1">
<li><a><span>•</span>Golden State Park</a></li>
<li><a><span>•</span>Sunrise Oaks City Park</a></li>
</ul>
</li>
</ul>
<ul class="map-poi-nav-dropdown">
//Parent #2
<li class="sub-menu-link" id="sub-menu-link-2">
<a href="#">
<img src="https://svgshare.com/i/ADc.svg"> Dining
</a>
</li>
<li class="sub-menu">
<ul class="sub-menu-list" id="sub-menu-list-2">
<li><a><span>•</span>The Loft Grill</a></li>
<li><a><span>•</span>Fish Grill & Bar</a></li>
</ul>
</li>
</ul>
</div>
You can use jQuery's .next() like so:
$(".sub-menu-link").click(function() {
$(this).next(".sub-menu-link").slideToggle(100);
$(this).toggleClass("active-menu-link");
})
Or you can chain them and use ES6 arrow syntax to make it more concise:
$(".sub-menu-link").click(() => $(this).toggleClass("active-menu-link").next(".sub-menu-link").slideToggle(100));
You should try this if your list and link ids have similiar pattern as in the code you have shown
$('#sub-menu-link').click(function() {
var id = $(this).attr("id").replace("sub-menu-link", "")
$('#sub-menu-list-'+ id).slideToggle(100);
$(this).toggleClass('active-menu-link');
});
I need to acces an element that has a certain style.
This is my structure
<ul>
<li> Hi </li>
<li> bye </li>
<li> third one </li>
</ul>
The list items are placed on top of each other (last one first) and I can dislike something or like something. Once I do that, it gets a style display:none like following:
<ul>
<li> Hi </li>
<li> bye </li>
<li style:"display:none;"> third one </li>
</ul>
Now after I did that I want to be able to acces the last element that does not have display:none, (the bye) how can I do this?
I was thinking of something in the form of:
var myId = $("#slider > ul li").last().attr("id");
But obviously I always get the ID of the item that is hidden since its still there.
Can I do something like select last where !display:hidden ?
Can I do something like select last where !display:hidden ?
Yes, with jQuery's :visible pseudo-class:
var myId = $("#slider > ul li:visible").last().attr("id");
(Note: Your li elements don't actually have id values, but that's a tweak.)
Live Example:
var listItem = $("#slider > ul li:visible").last();
$("<p>")
.text("Text of last visible item: " + listItem.text())
.appendTo(document.body);
<div id="slider">
<ul>
<li>Hi</li>
<li>bye</li>
<li style="display:none;">third one</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Can use ':visible' selector
var myId = $("#slider > ul li:visible").last().attr("id");
It should work using:
$("#slider > ul li:visible").last().attr("id");
https://api.jquery.com/visible-selector/
so your inline styling is a bit off it should be
<ul>
<li> Hi </li>
<li> bye </li>
<li style="display:none;"> third one </li>
</ul>
You could do a few different things, best is probably just iterate through and check for where display = none, then go to the previous element:
$('ul').children().each(function(e) {
if($(this)[0].style.display == 'none') {
console.log($(this).prev());
}
})
I'm using jstree and I want to access the IDs and names of all checked nodes in my HTML tree in order to present them together in a summary.
This is my code:
$("#summary").click(function () {
var id_arr = new Array();
var text_arr = new Array();
$("#tree").jstree('get_checked').each(function (index) {
id_arr.push($(this).attr("id"));
text_arr.push($(this).text());
});
alert("Your Selection: " + id_arr.join() + " " + text_arr.join());
});
While id_arr.push($(this).attr("id")); returns only the IDs of the relevant checked nodes (only the parent node ID when all children of the parent node are checked as well), text_arr.push($(this).text()); returns all the names of the checked nodes (name of checked parent and names of all of its children).
Do you have any ideas how to return only the names of the checked parent?
I already considered adding a hidden HTML attribute (as in <li id="123"> <a title="ID:123" hidden="name of node 123">name of node 123</a></li>) to my tree nodes and using .attr("hidden") instead of accessing node.text() but I think that there must be a better solution.
Any help would be much appreciated!
Update:
The HTML of the tree (my real tree is quite extensive but I think this one will do):
<div id="tree">
<li id="123"> <a title="ID:123">tree</a>
<ul>
<li id="234"> <a title="ID:234">leaf tree</a>
<ul>
<li id="345"> <a title="ID:345">oak</a>
<ul>
<li id="456"> <a title="ID:456">white oak</a></li>
<li id="567"> <a title="ID:567">German oak</a></li>
</ul>
</li>
<li id="678"> <a title="ID:678">lime</a></li>
</ul>
</li>
<li id="789"> <a title="ID:789">conifer</a>
<ul>
<li id="890"> <a title="ID:890">pine</a></li>
<li id="901"> <a title="ID:901">spruce</a></li>
</ul>
</li>
</ul>
</li>
</div>
Example: When choosing "oak", the return should be only "345 oak" and not "345 oak white oak German oak".
By the way, my idea with "hidden" doesn't work, because the elements written in there are, well, hidden.
I found a solution:
text_arr.push($(this).find("a:first").text());
The result of .text() is a string containing the combined text of all matched elements; in this case all text contained between the li-tags of the element referenced by $(this), including the text of the sub nodes.
By adding .find("a:first").text() only the text between the first a-tag is contained in the string.
My code:
<div id = "1">
<h1>Heading 1</h1>
<p class = "V">VVV</p>
<ul>
<li>line 1</li>
<li>line 2</li>
</ul>
<p class = "A">AAA</p>
</div>
<div id = "2">
<h1>Heading 2</h1>
<p class = "V">VVV</p>
<ul>
<li>line 1</li>
<li>line 2</li>
</ul>
<p class = "A">AAA</p>
</div>
$('ul').hide();
$('p.A').hide();
$('p.V').click(function(){
$(this).next('ul').slideDown('slow');
$(this).hide();
$(this).closest('p.A').show(); // <-- How do I select 'p.A' in the current div?
});
http://jsfiddle.net/S8xcz/7/
This works great up until 'p.V' is hidden. From there, I need to display the 'p.A' (the 'up arrow').
How do I navigate to this?
I'm assuming that hidden elements are still navigable - is this correct?
The closest method goes up the DOM tree to find an ancestor, you probably want to use nextAll('p.A').
http://jsfiddle.net/ambiguous/pWDth/
Or parent() and find(): $(this).parent().find('p.A').show();
http://jsfiddle.net/ambiguous/pWDth/1/
Or perhaps siblings: $(this).siblings('p.A').show();
http://jsfiddle.net/ambiguous/pWDth/2/
I'd probably use $(this).parent().find('p.A') as that's the least sensitive to how the HTML is arranged.
Replace
$(this).closest('p.A').show();
with
$(this).siblings('p.A:first').show();
I've been trying to get this problem solved, but I can't seem to figure it out without some serious workarounds.
if I have the following HTML:
<ul>
<li class="parent"> headertext </li>
<li> text </li>
<li> text </li>
<li> text </li>
<li class="parent"> headertext </li>
<li> text </li>
<li> text </li>
</ul>
Now, how do I now just select the <li> tags following the first parent (or second, for that matter)? Basically selecting an <li> with class="parent" and the following siblings until it reaches another <li> with the parent class.
I could restructure the list with nested lists, but I don't want to do that. Any suggestions?
actually, you can easily do this using nextUntil().
no need to write your own "nextUntil" since it already exists.
ex. -
$(".a").nextUntil(".b");
or as suggested by Vincent -
$(".parent:first").nextUntil(".parent");
The root of your problem is that the <li>s you have classed as parent really are NOT parents of the <li>s "below" them. They are siblings. jQuery has many, many functions that work with actual parents. I'd suggest fixing your markup, really. It'd be quicker, cleaner, easier to maintain, and more semantically correct than using jQuery to cobble something together.
I don't think there is a way to do this without using each since any of the other selectors will also select the second parent and it's next siblings.
function getSibs( elem ) {
var sibs = [];
$(elem).nextAll().each( function() {
if (!$(this).hasClass('parent')) {
sibs.push(this);
}
else {
return false;
}
});
return $(sibs);
}
You will have to run the loop yourself since jQuery does not know how to stop on a specific condition.
jQuery.fn.nextUntil = function(selector)
{
var query = jQuery([]);
while( true )
{
var next = this.next();
if( next.length == 0 || next.is(selector) )
{
return query;
}
query.add(next);
}
return query;
}
// To retrieve all LIs avec a parent
$(".parent:first").nextUntil(".parent");
But you may be better using a really structured list for your parent/children relationship
<ul>
<li class="parent"> <span>headertext</span>
<ul>
<li> text </li>
<li> text </li>
<li> text </li>
</ul>
</li>
<li class="parent"> <span>headertext</span>
<ul>
<li> text </li>
<li> text </li>
</ul>
</li>
</ul>
$("li.parent ~ li");
I know this is a very old thread, but Jquery 1.4 has a method called nextUntil, which could be useful for this purpose:
http://api.jquery.com/nextUntil/
<html>
<head>
<script type="text/javascript">
$(document).ready(function() {
$("a").click(function() {
var fred = $("li").not('.parent').text();
$('#result').text(fred);
});
});
</script>
</head>
<body>
Click me
<ul>
<li class="parent"> headertextA </li>
<li> text1 </li>
<li> text2 </li>
<li> text3 </li>
<li class="parent"> headertextB </li>
<li> text4 </li>
<li> text5 </li>
</ul>
<div id="result"></div>
</body>
</html>