Jquery :first selector give second element instead of first - javascript

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.

Related

How to check if two <tr> elements are equal when ignoring some inner <td> elments?

I am just wondering if is it possible in JavaScript or jQuery to check if two DOM elements are equal when ignoring inner elements.
For example, how to compare two <tr>'s and ignore particular <td>'s? Is it possible?
Here is a particular case: (ignore td with text1 and text2 values and compare only the date values. Important notice: td elements are without id attributes).
<tr id="row1" class="row">
<td>2010-09-01</td>
<td>text1</td>
</tr>
<tr id="row2" class="row">
<td>2010-09-01</td>
<td>text2</td>
</tr>
EDIT: snippet added
if ($('#row1 tr td:eq(0)').html() == $('#row2 tr td:eq(0)').html())
{
alert("same")
}
I would have thought that the only content within a tr should be td elements, so why not just compare the td's you're interested in and ignore the one you aren't?
Updated:
If you are sure of the td position in tr, you can compare:
if($("#row1 > td").eq(0).text() == $("#row2 > td").eq(1).text())
{
}

Using querySelector() to obtain last td element

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;

How to select tr based on td

I am trying to select array of "tr" based on "td" class, once I got the array I want to get array of all tr's custom "data-fid" value.
This what I got,
var rows = $("#tableB tr").children(".New.selected") // returns td, but I want tr
Once I got rows, I want to get array of there data-fid values,
var selectedValues = rows.attr('data-fid'); // not sure if it will work but i guess this is how i would do it
I am trying to google but my luck with finding right wording is just failing badly todya.
<table id="tableB" class="dmctable2">
<tr data-fid="1" Class="selected"><td></td><td></td><td class="New selected"></td></tr>
<tr data-fid="2"></tr>
<tr data-fid="3" Class="selected"></tr>
</table>
you can use :has() selector for that.
Selects elements which contain at least one element that matches the specified selector.
Like this:
$("#tableB tr:has(.New.selected)")
and to get the data values in array:
$("#tableB tr:has(.New.selected)").map(function(){return $(this).data("fid");}).get();
An other alternative which is faster would be to select the .New.selected element and then access to its parent:
$("#tableB tr .New.selected").parent('tr')

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

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