how to select parent of a parent? - javascript

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.

Related

Is there a way to reach parent's sibling in jquery?

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

Selector for a list-item containing a child element with a specified attribute value

I'm trying to display a particular item in a list based on a specific href value within an <a> tag.
<ul id="images">
<li class="other-image" style="display: none;">
<a target="_blank" href="http://www.example.com/page.html">
<img src="http://www.test.com/home/pic.jpg">
</a>
</li>
<li class="other-image" style="display: none;">
<a target="_blank" href="http://www.exmaple.com/index.html">
<img src="http://www.example-image.com/image.jpg">
</a>
</li>
<li class="other-image" style="display: none;">
<a target="_blank" href="http://www.example1.com/test">
<img src="http://www.example-image1.com/image1.jpg">
</a>
</li>
</ul>
$(document).ready(function () {
$("#images").find("li").fadeIn().delay(10000).fadeOut();
});
For example I want to display an item where href="http://www.exmaple.com/index.html". I wouldn't want to use index instead because this item could have a different index as more items are added/removed from the list. I've tried writing the selector several different ways (below) to only select a list item with this a specific href value with no success.
Attempt #1:
$("#images").find("li").filter($("a[href='http://www.exmaple.com/index.html']")).fadeIn().delay(10000).fadeOut();
Attempt #2:
$("#CCCImages").find($("a[href='http://www.exmaple.com/index.html']")).fadeIn().delay(10000).fadeOut();
Attempt #3:
$("#CCCImages").children($("a[href='http://www.exmaple.com/index.html']")).fadeIn().delay(10000).fadeOut();
Any suggestions would be greatly appreciated.
Attempt 1 fails because you are looking for an anchor tag in a list of lis. It is not looking at the children.
Attempt 2 fails since you are not fading the li
Attempt 3, anchor is not a child.
There are tons of ways to do it.
One is
$("a[href='http://www.exmaple.com/index.html']").closest("li").fadeIn();
When using jQuery selectors, and particularly after invoking [DOM traversal] methods, you must be mindful of the current matched set when calling methods on the jQuery object. As an example, to break down your first attempt,
$("#images") // Targeted set is only the <ul>
.find("li") // Only the 3 <li> elements
.filter($("a[href='http://www.exmaple.com/index.html']")) // matches nothing.
.fadeIn()
.delay(10000)
.fadeOut();
The filter examines each <li> and checks if it is also an <a>, so they all fail and are left out. As the docs point out:
The supplied selector is tested against each element; all elements matching the selector will be included in the result.
Tweaking the above, we can easily correct the filter to be a little more effective. First, target the desired <li>s: $("#images li")
Then filter the results using has, limiting your result-set to those which have an anchor link matching your criterion: .has("a[href='http://www.exmaple.com/index.html']")
And finally, do your fading.
$("#images li")
.has("a[href='http://www.exmaple.com/index.html']")
.fadeIn()
.delay(10000)
.fadeOut();
Of course, if you're curious, the filter method can also be leveraged in a useful way to accomplish this. There is an overloaded variant of the method which accepts a function to use for filtering. In this case, the usage below is functionally equivalent to using has, but more verbose.
$("#images li").filter(function() {
return $(this)
.find("a[href='http://www.exmaple.com/index.html']")
.length > 0;
})
.fadeIn(); // etc.

appending elements to a list

I am trying to append a list element dynamically to already existing list.
I've a list in the form,
<ul id="test">
<li class="testField">YYAAHOOOOOO<li>
</ul>
I am trying to add an extra item to this list using jQuery append or after...
What I did was:
$(".testField").after("<li class='testField'>TEST MESSENGER</li>");
Used after function as append did not work, the after function works fine first time as there is only one element with the class name testField, but as the list grows, the after function will add the list items to all elements present,
To make it clear, on first trial I will get an output:
<ul id="test">
<li class="testField">YYAAHOOOOOO<li>
<li class='testField'>TEST MESSENGER</li>
</ul>
If I try the to add another element now for example <li class='testField'>GOOGLE</li>, the output will be like:
<ul id="test">
<li class="testField">YYAAHOOOOOO<li>
<li class='testField'>GOOGLE</li>
<li class='testField'>TEST MESSENGER</li>
<li class='testField'>GOOGLE</li>
</ul>
I thought about using ids, but I am trying to have an option to remove elements from the list too... So if I try to append to an undefined id, it will return error. Is there anyway to find the first element inside a list and append the element to that first one?
Try:
$(".testField:first").after("<li class='testField'>TEST MESSENGER</li>");
this will make sure that you are appending after the first element only
Alternatively, you could do this without jQuery:
var li = document.createElement('li'); // Create a List item.
li.setAttribute("class", "testfield"); // Set the li's class
li.addChild(document.createTextNode("Your Text Here!")); // Set the li's text
document.getElementById("test").addChild(li); // Append the li to the list
It's slightly more code, yes, but it's pretty much what jQuery does under the hood. (And faster, too)
If you want to add the new ul after the first li already in the list, replace the last line with:
var ul = document.getElementById("test");
if(ul.children.length > 1){ // If the list has 2 or more children (li's)
ul.insertBefore(li, ul.children[1]); // Insert the new item before the second item in the list.
}else{
document.getElementById("test").addChild(li);
}
Now, why am I posting a answer that requires more code?
Anything that can be done in jQuery can be done in native JS. I think it's good to have multiple different answers available on SO, especially if they use different techniques to do the same thing. That way, users can chose for themselves: short'n easy (jQuery), or if they don't want to use the library, native code.

JQUery find and match parent based on a dynamic child class

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')); });

Javascript getElementsByTagName

I'm trying to use the getElementsByTagName("a") method to get all the elements under a specific tag.
However, I don't want every anchor tag. How would I narrow it so I only select all the anchor tags under the the ul tag for "someListClass" name?
<ul class="someListClass"> <li><a href... /></li>... </ul>
I know in jQuery you can just select with $(".someListClass a").
How would I do it without using jQuery?
Give your ul an id and then use
<ul id="ulid" class="someListClass"> <li><a href... /></li>... </ul>
document.getElementById ( "ulid" ).getElementsByTagName ( "a" );
element.getElementsByTagName
elements = element.getElementsByTagName(tagName);
elements is a live NodeList of found
elements in the order they appear in
the subtree.
element is the element from where the
search should start. Note that only
the descendants of this element are
included in the search, but not the
element itself.
tagName is the qualified name to look
for. The special string "*" represents
all elements. For compatibility with
XHTML, lower-case should be used.
you can use
element.getElementsByTagName(tagName)
where element is the UL item... so grab the UL item then search against that. something like:
<ul class="someListClass" id="myList"> <li><a href... /></li>... </ul>
var theList = document.getElementById('myList');
var listItems = theList.getElementsByTagName('li');
you want getElementsByClassName http://www.quirksmode.org/blog/archives/2008/05/getelementsbycl.html
links = document.getElementsByClassName("someListClass")[0].getElementsByTagName("a")
Without a framework, I can think of no other way than going though each element manually and to iterate its parents. If one of them has the class "somelistClass", add it to the stack. Otherwise, not.
If you are looking for the children of a single element, phoenix's approach is the way to go.

Categories

Resources