I have a button inside a div. When clicked, i will need to grab the length of a list that is a sibling to the parent container. maybe so even a grandparent container.
The gist of the code looks something like this below. (My actual code is actually nested deeper than this example. I would like to know how to target part a sibling of a parent or grandparents or even great great grandparent...)
HTML
<div>
<div class="button-parent">
<div class="button-containers">
<button>Click Here!</button>
</div>
</div>
<div class="list-container">
<ul class="lists">
<li>bar</li>
<li>bar</li>
<li>bar</li>
<li>bar</li>
<li>bar</li>
</ul>
</div>
</div>
jquery
$('button').parent('button-parent')
.closest('list-containers').length
.closest() finds the closest ancestor (parent), so it won't find your .list-container.
You can do this a few ways though...
Give your surrounding div a class and use .find() to locate your list if it is the only list in your parent div:
$('button').closest('.parent-div').find('.list-container');
Use next() if .list-container will always be the next item after .button-parent:
$('button').closest('.button-parent').next('.list-container');
You can use .siblings() if .list-container will always be on the same DOM level as .button-parent:
$('button').closest('.button-parent').siblings('.list-container');
From there you can fulfil the rest of your requirement to capture the length of the list by selecting all the li elements and counting them. If we use number 1 above as an example, it might look something like this:
const list = $('button').closest('.parent-div').find('.lists');
const items = list.children();
const count = items.length;
NOTE: The selection for list in this example targets ul.lists rather than .list-container, as this allows us to count using children(), which is much less intensive than find().
I suppose you can use Use parents([selector]) or closest([selector]) with siblings([selector])
parents() looks for ancestors, closest() be used as well if you want to select only the first going upward in the ancestry
siblings() select for siblings
you can pass them selectors or use eq()
one more things your jquery snippet doesn't seem to include . for class selector
Three methods that I tried and worked are
$('button').parents().eq(1).siblings('.list-container');
$('button').parents('.button-parent').siblings('.list-container');
$('button').closest('.button-parent').siblings('.list-container'));
Check out this jsfiddle, i have selected list-container using the three methods
Related
$('#mainlist').last().hide().fadeIn(200);
Why is this hiding, and then fading in all the items in the list instead of just the last one?
Edit: The section of HTML:
<div id="mainbox">
<ul id = "mainlist">
</ul>
</div>
My js appends to the ul with a li, and then it runs the first code shown above.
It's because there's only one element in the list returned by $("#mainlist"). You're selecting the last #mainlist which is your ul.
The .last() method selects the last element in a list of DOM elements, not the last child of the elements selected.
From the jQuery docs:
Given a jQuery object that represents a set of DOM elements, the
.last() method constructs a new jQuery object from the last element in
that set.
You want something like $('#mainlist li').last().hide().fadeIn(200); instead.
It's because your #mainlist element has another child/wrapping <ul> before the list items (so it's hiding the wrapping <ul>, thus all the elements). Maybe try be more specific with your selector
$("#mainlist li").last().hide().fadeIn(200);
EDIT By the way, this assumes your <ul> is filled with <li> tags.
I'm trying to find the element using jQuery from the following html.
<ul class="gdl-toggle-box">
<li class="">
<h2 class="toggle-box-title"><span class="toggle-box-icon"></span>Volunteer Form</h2>
<div class="toggle-box-content" style="">
</div>
</li>
</ul>
What I'm looking to do is when the h2 is clicked find the li above the h2 add a class active to it. Tried a few different calls but no luck.
EDIT
The biggest issue is that there are multiple toggle boxes on a page so something like this works on pages with a single toggle but pages with multiple the result is they all open together.
var gdl_toggle_box = jQuery('ul.gdl-toggle-box');
gdl_toggle_box.find('li').each(function(){
jQuery(this).addClass('item');
});
gdl_toggle_box.find('li').not('.active').each(function(){
jQuery(this).children('.toggle-box-content').css('display', 'none');
});
gdl_toggle_box.find('h2').click(function(){
if( jQuery('.item').hasClass('active') ){
jQuery('.item').removeClass('active').children('.toggle-box-content').slideUp();
}else{
jQuery('.item').addClass('active').children('.toggle-box-content').slideDown();
}
});
You can use closest.
closest will match the first parent element that matches the selector traversing up the DOM tree.
Demo
$('h2.toggle-box-title').click(function(){
$(this).closest('li').addClass('active');
});
Try this.
$('h2.toggle-box-title').click(function(){
$(this).parent().addClass('newclass');
});
try this:
$('h2.toggle-box-title').click(function() {
$(this).parent('li').addClass('active');
});
On you click in the button you can use the event:
$("something").parent().find("h2.myClass");
// And if you want you can add class after you find you object
http://api.jquery.com/find/
Selecting an element's parent
In order to select an element parent, you can use the parent() function.
Try this:
$('h2.toggle-box-title').click(function() {
$(this).parent('li').addClass('active');
});
*to be more specific, you target the parent you would like to choose by specifying its selector
Check the jQuery API Documentation here
parent() - Get the parent of each element in the current set of matched elements,
optionally filtered by a selector.
the jstree looks something like this :
<ul>
<li id ="head" >TITLE
<ul>
<li id="body">BODY
<ul>
<li id="foot">FOOTER
</li>
</ul>
</li>
</ul>
</li>
</ul>
This is basically a tree with depth 3.
I just want to know if its possible to access the id "head" from the id " foot"
something like
jQuery(#foot).parent().parent();
or
jQuery(#foot).parent().parent.attr("id");
or something similar
IDs are supposed to be unique across your page, so you shouldn't have more than one element with the same ID, and hence you should be able to use just $('#head') to select it.
In your case, I suppose you want to use a class 'head', which could appear many times in your list.
The easiest way to achieve it would be using jQuery closest(). It finds the first parent matching given selector.
$('#foot1').closest('.head')
http://api.jquery.com/closest/
You could always use the parents method:
$('#foot').parents('#head');
Although, since the head has an ID, you could just look it up directly: $('#head')
You cold write:
$('#' + $('#foot').parent().parent().parent().parent().prop('id')).do something with head
Make sure to read about the difference between .prop() & .attr()
Assuming these are the only <ul> and <li> elements on the page.
$('#foot').parents('li:last').attr('id');
Should give you the id which is head.
parents() function lists the parents of element from closest to farthest. So the last li element will be the one with id head.
Fiddle here.
Ok it's a little hard to explain in a single title but basically I have a dynamic class added to a child element based on it's parent's dynamic class. Added so:
$('ul').each(function(key){
if ($(this).hasClass('sortable')){
$(this).addClass('parent' + key);
$(this).children().addClass('parent' + key);
};
});
The structure is pretty simple after this:
<ul class="parent0">
<li class="parent0">
<ul class="parent1">
<li class="parent1"></li>
</ul>
</li>
</ul>
Now the UI has the user move these li outside of the parent and placed elsewhere. Later on, I want to check the element and then match it to it's corresponding (original) parent. It can't be $(this) parent because it will be moved out of the parent but the classes still remain.
So the check is looking for .parent(n) and then finding the ul with .parent(n) eventually this code will live inside:
$('sortable li').appendTo($('THIS-IS-THE-DYNAMIC-CLASS'));
So I'm assuming the find will be before this but I don't know how to write that.
I would use a different attribute other than class so it can be wholly unique. Either use $(this).data or $(this).attr. And I would recommend assigning IDs to the parent (or a different attribute) that, again, can be wholly unique. This will keep things cleaner in my opinion.
For example...
Assuming:
$(this).attr('parentClass', '.parent' + key);
then
$('.sortable li').each(function() { $(this).appendTo($(this).attr('parentClass')); });
I have a blob of HTML that I'm retrieving using simple jQuery selectors, something like the following:
<div id="stuff">
<ul>
<li>some</li>
<li class="ninja">stuff</li>
</ul>
</div>
I'm basically doing:
var myblock = $("#stuff").html();
now I want to inject an additional li element to the bottom of that li list with very similar attributes to the li above it, but i want to change the class ninja to class samurai.
What's the best way of going about that with jQuery?
Simply select the <ul> and append the <li> to it
$("#stuff ul").append('<li class="samurai">stuff</li>');
If you actually wanted to copy the last <li> element, change the class then add to the list, then you could do something like this
var ul = $("#stuff ul");
ul.append(ul.find('li:last').clone().removeClass().addClass("samurai"));
pass true into clone() if you also want to copy event handlers too.
The problem with taking a whole chunk of HTML, changing an element and then reinserting is that any event handlers set up on elements that will be replaced when you reinsert the HTML will be lost, so it's more elegant/ and less cumbersome/intrusive to simply manipulate the part of the DOM that you need to.