getting table row of $this parent siblings table ! - javascript

i have a href link under my table and i want to be able to manipulate table rows by clicking on that link but i cant get them !
here is my html
<div>
<div> <a href="#remove" class="removelink" > remove </a> </div>
<table>
<tr> <td></td> </tr>
</table>
</div>
i want to do something like:
$('.removelink').click(function(){
$(this).parent().siblings('table tr:last').remove();
})
i can get to the table by
$(this).parent().siblings('table')
but i cant get rows by something like
$(this).parent().siblings('table tr')

You can use find to get to the tr from the table:
$('.removelink').click(function(){
$(this).parent().siblings('table').find('tr:last').remove();
});
Here's a working example. If your HTML structure is always exactly as you've shown, you could use next() instead of siblings('table') for slightly shorter code.
The problem with your current code is that siblings('table tr') will look for a sibling of the div which is a tr, and there are none!

.siblings(selector) will return all siblings of a certain element which match the selector.
.siblings('table tr') will only return something if the context element has tr elements as siblings but the div does not.
Just use .find:
$(this).parent().siblings('table').find('tr').last()

var $context = $(this).parent().siblings('table');
$("tr:last", $context);

Related

How to get last element in the .find() object by jquery

I have DOM like this:
<div class="parent">
<button class="add-tr">Add</button>
<table class="child">
<tr data="0"></tr>
<tr data="1"></tr>
...
</table>
</div>
<div class="parent">
<button class="add-tr">Add</button>
<table class="child">
<tr data="0"></tr>
<tr data="1"></tr>
...
</table>
</div>
...
When I click on the Add button, I would like to get the value of the data attribute from the last of it own parent class.
I am using this method to get the last element,but it doesn't work.
$('.add-tr').click( function() {
var last = $(this).parent().find('.child:last').attr('data');
alert(last);
})
Any idea why? Or any other suggestion to get the last element in the table?
UPDATE
Yes, I found the problem, turn out is I forgot the 'tr'. Thanks for your guys answer. All your guys giving the correct answer, I wish I can accept all your answers. Thanks
Try this
var last = $(this).parent().find('.child').find('tr').last().attr('data');
In your example you get last table, but you need get last tr
Example
'.child:last' selector will select the last element having child class. As child class is applied to <table>, this selector will select table element, while you want to select last <tr>.
As there is no data attribute on <table>, .attr('data') on it will return undefined.
To get the value of data attribute on last <tr> use the selector tr:last.
var value = $(this) // Button that is clicked
.parent() // Direct parent element i.e. div.parent
.find('.child tr:last') // Get the last <tr> inside .child
.attr('data'); // Get value of data attribute
As the .child element is next to the button, next() can be used to get the table.child element.
var value = $(this) // Button that is clicked
.next('.child') // Next element i.e. table
.find('tr:last') // Get last <tr>
.attr('data'); // Get value of "data" attribute
I'll recommend to use data-* attribute to store data in custom attribute.
<tr data-num="0">Foo</tr>
<tr data-num="1">Bar</tr>
And to get the value of custom data attribute use data()
.data('num')
If you just want to get the index of the last tr, there is no need to store that on element. You can get the index by using the index().
.index()
This will return index of an element. Note that this is zero-based index which is exactly how you want.
$(".parent").click(function(){
$(this + " tr:last-child").attr("data");
});
should do.
Your code was almost correct, you missed tr:last , i.e.:
var last = $(this).parent().find('.child tr:last').attr('data');
DEMO
http://jsfiddle.net/tuga/vr1knxqq/3/
$('.add-tr').click( function(event) {
var last = $(event.target).next().find("tr").last().attr("data");
alert(last);
})
fiddle-example
You can get an array of the tr elements by using find('.child tr')
and to get the last element in that array you can use last().
Putting it all together you have this:
$('.add-tr').click( function() {
var lastTr = $(this).parent().find('.child tr').last(),
lastData = $(lastTr).attr('data');
alert(lastData);
});
I have setup a codepen here http://codepen.io/anon/pen/aOzmKg to show this working.

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 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 absolute DOM path of html element

I'm having problems with html DOM.
How do I get the value from this path:
html body div table tbody tr td table tbody tr td table tbody tr td table tbody tr td form table tbody tr td
I can only find stuff like getElementbyID/tag/name/class etc.
How do I get the absolute DOM 'path' of the td element (let's say the 3rd cell of the second row in that table)?
I've been looking everywhere but cannot find a simple answer without ID/Class etc involved.
You could use querySelector(), but it doesn't have great support...
var elem = document.querySelector('html body div table tbody tr td table tbody tr td table tbody tr td table tbody tr td form table tbody tr td');
Otherwise just use a library that allows you to use CSS selectors, such as jQuery.
var $elem = $('html body div table tbody tr td table tbody tr td table tbody tr td table tbody tr td form table tbody tr td');
By the way, selecting like this is horrible for performance. Absolutely terrible. Have a read up on CSS selectors to learn why.
First, consider whether you do really need full paths. Referring to IDs or classes is more robust as they have less moving parts.
If full paths are what you need, you may wish to use XPath, as it's specifically designed for finding elements by path.
Here's a simple cross browser XPath library - there are many others.
Looks like you may want something like this:
For the following sample HTML,
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="findit.js"></script>
</head>
<body>
<div id="header">
<h1>Welcome to my ASP.net site!</h1>
</div>
<div id="h440292">
<table>
<!-- tbody omitted, but some (all?) browsers add it -->
<tr>
<td>junk</td>
<td>junk</td>
<td>junk</td>
</tr>
<tr>
<td>junk</td>
<td>junk</td>
<td>pick me!</td>
</tr>
</table>
</div>
</body>
</html>
this jQuery code will find the cell that says "pick me!"
$(function () {
var $resultCell = $("body")
.children("div").eq(1)
.children("table")
// Note I have to add this even though
// I omitted the tbody in the HTML markup
.children("tbody")
.children("tr").eq(1)
.children("td").eq(2);
alert($resultCell.text());
});
If performance becomes a problem, you may need to resort to doing something similar using the native DOM methods.
I am playing with this idea. I want to be able to find any node on a page (using a headless browser). Trying to build an absolute node path I created a recursive function, works but I am finding it is not completely unique which is annoying. On here for example, each post is templated so selecting text in the third response will reveal the same node path up the HTML tag as the first post
const buildPath = (node) => {
console.log(node);
if(node.tagName !== "HTML") {
path.unshift(node.tagName.toLowerCase())
buildPath(node.parentNode)
}
};
const path = [];
builtPath(<start node>);
document.querySelector(path.join(" "))
but this is where I am stuck now. Some things don't have any specific classes or names or ids to add to that. I may need to capture the innertext or innerhtml and try to match that. Kinda annoying. I suppose you could load like D3 and inject an incremental ID as data but then the site can't change at all, which may be true for this method too but I would think less so.

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