Getting child element of a child element of a parent with ID - javascript

I need to get to the child of the child of the child of an element with an id = "part1" with javascript. So essentially, I want to get to the 3rd row of the 3rd table of the span element but I can't seem to get it to work :(
<span id = "part1">
<table> </table>
<table> </table>
<table>
<tr> ... </tr>
<tr> ... </tr>
<tr> ... </tr> (get this row)
</table>
</span>

Non-jQuery solution
var span = document.getElementById('part1');
var row = span.getElementsByTagName('table')[2].childNodes[2];
jQuery solution
Using :eq selector:
var $row = $('#part1 > table:eq(2) > tr:eq(2)');
Using :nth-child selector:
var $row = $('#part1 > table:nth-child(3) > tr:nth-child(3)');
:eq and :nth-child selectors selects all elements that are the nth-child of their parent. However :eq follows "0-indexed" counting and nth-child follows "1-indexed".
Be aware that :eq and nth:child selectors work differently. In this case it would do the same because you only have table elements inside span#part1.
From jQuery documentation:
The :nth-child(n) pseudo-class is easily confused with :eq(n), even
though the two can result in dramatically different matched elements.
With :nth-child(n), all children are counted, regardless of what they
are, and the specified element is selected only if it matches the
selector attached to the pseudo-class. With :eq(n) only the selector
attached to the pseudo-class is counted, not limited to children of
any other element, and the (n+1)th one (n is 0-based) is selected.
Reference:
:nth-child() Selector

try this
this.parentNode().getElementsByTagName("table")[2].childNodes[2];

I prefer using .find() rather than the sizzle engine. Something like this:
var TheThirdRow = $('#part1').find('table')
.eq(2)
.find('tr')
.eq(2);

Related

Jquery :first selector give second element instead of first

I want select first row from any cell so I just wrote javascript like.
var curcontrol = $("#cellno_111");
var firsttd= $(curcontrol).parents("table tbody tr:first");
alert($(firsttd).text());
And my table is below
<table id="idTable_1" border="1px" width="97%" class="tblDragTable" data-numberofrows="2" data-numberofcolumns="2">
<tbody>
<tr id="trno_10">
<td class="tblCell" id="cellno_100">0</td>
<td class="tblCell" id="cellno_101">0</td>
</tr>
<tr id="trno_11" height="1">
<td class="tblCell" id="cellno_110" width="1">1</td>
<td class="tblCell selectedCell" id="cellno_111" width="1">1</td>
</tr>
</tbody>
</table>
when I use find() it giving me correct result
var curcontrol = $("#cellno_111");
var firsttd= $(curcontrol).parents("table tbody").find("tr:first");
But I just want to know why the above code return second tr instead of first tr
HERE IS MY JSBIN http://jsbin.com/lisozuvade/1/watch?html,js,output
The reason why it fails is because calling parents with a filter of table tbody tr will only match the immediate parent TR. The other TR falls outside of the ancestors so :first will match the only TR it finds.
If you try this you will see what is going on:
alert($(curcontrol).parents('table tbody tr')[0].outerHTML);
returns this:
<tr id="trno_11" height="1">
<td class="tblCell" id="cellno_110" width="1">1</td>
<td class="tblCell selectedCell" id="cellno_111" width="1">1</td>
</tr>
then try this:
alert($(curcontrol).parents('table tbody')[0].outerHTML);
which returns this:
<tbody>
<tr id="trno_10">
<td class="tblCell" id="cellno_100">0</td>
<td class="tblCell" id="cellno_101">0</td>
</tr>
<tr id="trno_11" height="1">
<td class="tblCell" id="cellno_110" width="1">1</td>
<td class="tblCell selectedCell" id="cellno_111" width="1">1</td>
</tr>
</tbody>
JSFiddle: http://jsfiddle.net/TrueBlueAussie/j28g27m1/
So your first example only looks at the ancestors (one TR) and returns the first match. The second example looks further back up the tree, then finds all TRs in the tbody then chooses the first one.
A preferred, slightly faster, way would be to use closest() and find()
e.g.
var curcontrol = $("#cellno_111");
var firsttd= $(curcontrol).closest("tbody").find("tr:first");
or faster yet (as selectors are evaluated right-to-left):
var curcontrol = $("#cellno_111");
var firsttd= $(curcontrol).closest("tbody").find("tr").first();
e.g. http://jsfiddle.net/TrueBlueAussie/j28g27m1/1/
You're asking for parents of #cellno_111, only that tr is.
Also keep in mind that :first is like .first() as it filters to the first element in the set of matched elements, it has nothing to do with being the first child of something. If you want multiple elements, which are first children you should use :first-child.
.parents(table tbody tr:first): query the parents of the element for a tr which is inside of table and tbody, then pick the first
.parents("table tbody").find("tr:first"): query the parents of the elements for a tbody which is inside a table, then find all trs inside of it, then pick the first of them
PS: I suggest using closest instead of parents as the go-to DOM navigation method for ancestors; most of the times it's way more practical and easier to understand.
Actually, you need to understand what each selector is doing. Try with several console.log, you'll see:
$(curcontrol).parents();
This return a set of elements. In this set, there is only 1 tr, the parent of your curcontrol td tag.
You can indeed filter this specific set by adding a extra filter :
$(curcontrol).parents("table tbody tr:first");
But as I just explained, the original set only contains a single TR, so the first one returned is actually the only one returned.
Your find() approach is different, you specify a specific (parent) element and with the find() you search trough children, which explains in this case the correct behaviour.
If I'm not mistaken, the parent hierarchy of cellno_111 is:
trno_11 -> tbody -> table
In your first example, the first tr parent cellno_111 finds is trno_11 and not trno_10. It does not have a trno_10 parent.
The reason it does work with find(), is because you select the tbody and then search for the first tr child the tbody has.

How do I use the nth-child selector with jquery's child selector?

This works fine:
$("#element").find("> tr > td > i > a")
But I'm trying to use the nth-child selector to say that I want a specific numbered child. For example, I want:
$("#element").find("> tr > td > i > a:nth-child(3)")
I'm not getting any results. Does anyone have any ideas on how I could select all the nth numbered children? Thanks in advance!
Firstly, this unless there's a great need to do direct descendant (the >) selectors, I don't see the need of including them, you can appropriately shorten your CSS selector too:
//Select 3rd <a> tag, within the context of #element td
$('a:nth-child(3)', '#element td');
//or
$('#element td a:nth-child(3)')
Fiddle: http://jsfiddle.net/KGWuK/
Although, currently your selector provided with the question will only work if your HTML structure is:
<td>
<i>
<a>One</a>
<a>Two</a>
<a>Three</a>
</i>
</td>
Which isn't a very advisable style of markup. That's because the original selector is selecting <a> tags of those that a direct child of the <i>
I would recommend not using find as its not needed:
$("#element > tr > td > i > a:nth-child(3)")
This will find the tag located within the tag located within the table cell within a table row located within the element.
JSFiddle
Seeing that you have only 1 a with no sibling, i guess you are for the fourth element of your stack.
There is a jQuery method for that : .eq() :
$("#element").find("> tr > td > i > a:eq(3)");
or faster :
$("#element").find("> tr > td > i > a").eq(3);

Add class to element that doesn't have class - jQuery

In the table below only one td has class, another doesn't have class like:
<table id="bow-me">
<tr class="row-me">
<td class="show-me">Pet is Great</td>
<td>Pete is Greate</td>
</tr>
</table>
I tried something like:
if(!$("#bow-me tr td").hasClass("show-me")) {
$(this).addClass("know-me");
}
But this doesn't add the class know-me in my second td here.
I have attached the JSFiddle here
If I want to add Class to the second td only then how do I do?
Try attribute selector and :not() to get the <td> without any class
$('#bow-me tr td:not([class])').addClass('know-me');
Or if you want to specify which <td> like first or second, use :eq()
$('#bow-me tr td:eq(1)').addClass('know-me');
Doc reference
:not()
Attribute selectors
.eq()
You can use :eq() selector:
$('#bow-me tr.row-me td:eq(1)').addClass('know-me');
Updated Fiddle
or .eq()
$('#bow-me tr.row-me td').eq(1).addClass('know-me');
Updated Fiddle
the reason your code doesn't work is because
There are multiple td's found with your selector
$("#bow-me tr td")
You can't use the $(this) as a selector inside your if conditional statement. it has no valid reference as is.
Solution: you can cycle through the matched elements via each() function and then set up your conditional to check each one of the elements found - $(this) would work in this case
$("#bow-me tr td").each(function() {
if(! $(this).hasClass("show-me")) {
$(this).addClass("know-me");
}
});
check out the jsFiddle here
I gave this answer as an explaination as to why your approach does not work.
I prefer Anton's approach that uses the :not() pseudo selector.

Jquery Finding the closest link?

I want to be able to get the href from this type of code:
<tbody>
<tr class="odd">
<td class=" sorting_1">
The Link Text
</td>
</tr>
</tbody>
but I want to be able to click on the link itself, or the td.
Here is my CoffeeScript:
$("#myID tr td").click (event)->
event.preventDefault()
link = $(event.target).find("a").attr("href")
$("#anAjaxPod").load(link)
This works if one clicks on the td, but not if if one clicks on the link.
Edit: Updated question, I used find at first. This is just the last code I played with
Use .find() ; .closest() is to climb up the DOM tree testing self and ancestors. Here anchor tag is the child of td so you need to descend down. So find or a children selector is what you need.
$(this).find("a").attr("href")
Closest get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
$("#myID tr td").click(function(event){
event.preventDefault()
link = $(this).find("a").attr("href");
$("#anAjaxPod").load(link);
});
Fiddle
.closest() looks and self or ancestors where as you want to descendent, to find the descendent use find()
link = $(event.target).find("a").attr("href")
try this:
$(function(){
$("#myID tr td").click(function(){
Link = $(this).find("a").eq(0).attr("href");
$("#anAjaxPod").load(Link);
return false;
})
})

How to get inner tr tag using JQuery?

I am trying to grab documentnumber attribute from the tr tags inside tbody, and save it in an array.
Below is the html , I am working on
<tbody class="line-item-grid-body">
<tr data-group-sequence-number-field-index="" data-sequence-number-field-index="1" documentnumber="80" documentid="4133604" parent="80" class="line-item parent-line-item line-item-show reorderable-row droppable-element">
<td>
<table>
<tbody>
<tr></tr>
</tbody>
</table>
</td>
</tr>
<tr data-group-sequence-number-field-index="" data-sequence-number-field-index="1" documentnumber="80" documentid="4133604" parent="80" class="line-item parent-line-item line-item-show reorderable-row droppable-element">
</tr>
</tbody>
and this is what I did, which is not working. If I don't specify particular class then system also grabs inner tr tags, which I don't want
var docs = jQuery("#line-item-grid").find('tbody').find("tr[class='line-item parent-line-item line-item-show reorderable-row droppable-element']");
for (i=1;i<=docs.length;i++)
{
var tempValue = jQuery(docs[i]).attr('documentnumber');
alert(tempValue);
}
Any ideas?
There's several ways you could go about this. I would do the following....
var docs = $('.line-item-grid-body>tr');
Docpage: Child selector
Another option:
var docs = $('.line-item-grid-body').children('tr');
Bookmark and frequent this page ... Selectors - jQuery API
try this as your selector
$('tbody > tr','#line-item-grid');
Hmm i didn't test this (so check for typos), but off top of my head, i'd try something like this:
jQuery(".line-item-grid tbody > tr").each(function() {
alert($(this).attr('documentnumber');
});
You can define selectors one after another, pretty much same as in CSS.
Also check child selector (http://api.jquery.com/child-selector/) for selecting direct child elements.
Hope it helps

Categories