Using querySelector() to obtain last td element - javascript

I have a variable which is a node from the dom. I've managed to get all the way down to close to where I want to be:
myvar.querySelector('.tblItinPriceSummary tr')
Gives me this:
<tr>
<td>Subtotal</td>
<td align="right">$189.00</td>
</tr>
What I want is the textContent of the second td $189.
Is there anything I can add inside of querySelector so that I can append it with .textContent to get this piece of data?

You could either use :last-child or :last-of-type to access the last td element within the parent.
document.querySelector('.tblItinPriceSummary tr td:last-child').textContent;

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.

jQuery - cannot get col number of a td

I try to get a column number of a td by selecting the td by its class name. But it always returns -1. What is wrong?
js fiddle
HTML
<table >
<tbody>
<tr>
<td >apple</td><td class="current">banana</td><td>cherry</td>
</tr>
</tbody>
JS
console.log($("td.current:first").parent().parent().children().index($(this)));
You can use the variant of .index() that does not take any arguments, to get the index based on its sibling elements
console.log($("td.current:first").index());
Demo: Fiddle
Simply do:
console.log($("td").index($("td.current:first")));
As you have it, $(this) is pointing to the window object, and not the scope you think it is, which has not been defined in the context of the call.
Also note that index() works thusly: collection.index(member).
you don't neet to get parent then parent, Simply do this
$("td.current:first").index();

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.

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

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

Javascript access TR from TD

I have a table row, and within that, I have a td (whatever it stands for). I would like to change the class attribute of the TR my TD is in without using an ID or a name. Like that:
<tr>
<td onclick="[TR].setAttribute('class', 'newName')">My TD</td>
</tr>
How do I do it?
td stands for table data..
now .. in your case you need the parentNode property of the td ..
<tr>
<td onclick="this.parentNode.setAttribute('class', 'newName')">My TD</td>
</tr>
or as bobince suggested in his comment
<td onclick="this.parentNode.className= 'newName'">My TD</td>
In jquery, it would be really simple if you have the reference to your td:
$(this).closest('tr');
If you really don't want to take a dependency on jQuery, then you could just do a loop getting the parentNode and checking it's type as a more general purpose solution. In this case you could just get the parentNode since tr is always a direct parent of td. You can do something like this (note this was not tested):
var parent = myTd.parentNode;
while(true) {
if(parent == null) {
return;
}
if(parent.nodeName === "TR") {
return parent;
}
parent = parent.parentNode;
}
If you have the dom element in javascript, you can use .parentNode() which will give you the parent node, which should be the table row. Then you can set .className
If you can use jQuery it could be something like this
$("yourtdselector").closest("tr").attr("class","classname");
For your code
<tr>
<td onclick="changeClass(this,'classname')">My TD</td>
</tr>
function changeClass(elem, class)
{
elem.parentNode.className = class;
}
jQuery is probably the easiest way of doing this, you can use selectors such as:
$('table.mytable tr').addClass('red');
To add a class of 'red' to all tr's in table.mytable. That's just the tip of the iceberg - check it out it should do what you need.
Without any extra framework:
document.getElementById("theTableName").rows[1].cells[1].className = "someclassname";

Categories