Really next element with specific class - javascript

I am newbie in Jquery, sorry for my silly question.
Here is my HTML code :
<tr role="row" class="odd">
<td><input type="checkbox" class="mycheckbox" value="2166"></td>
<td class="sorting_1">2166</td>
<td><span class="myparentid">743</span>
</td><td>0</td>
</tr>
I would like to jump from 'mycheckbox' element to 'myparentid' element, ignoring the tree structure.
In Jquery, I tried something like :
var checkedRow = $(".mycheckbox");
var nextelem = checkedRow.next(".myparentid");
It does not work because next searches only in siblings...
Can you give me a hint ?
Thanks !

The easiest option is to go up to a common parent element (in this case the table row), then back down to the one you want:
$(".mycheckbox").closest("tr").find(".myparentid")
https://api.jquery.com/closest/
https://api.jquery.com/find/
Edit: To add some additional information:
$(".mycheckbox")
is the starting location, it's at: tr>td>input.mycheckbox
(where > means directly below in the html tree)
.closest moves up the tree until it finds a matching parent element, so .closest("tr") will find
<tr role="row" class="odd">
by looking at the direct parent "td", then it's direct parent "tr".
Normally I'd use a class here (<tr class="businessobjectcontainer">) (depending on what the business object is) then it can be a div or tr if you change this part of it later and seeing .odd I'd assume this is for styling and there'll be a .even - so that's not ideal as a selector. So "tr" would have to do.
.find() does the opposite of .closest and goes down the tree looking for a matching element, in this case .myparentid will find: tr>td>span.myparentid
which is what you're looking for.
.find() may not be the most efficient, but it's probably the most flexible as it means you can move the content of your tr around as much as you like.
A move efficient alternative might be to use:
$(">td>span.myparentid", $(".mycheckbox").closest("tr"))
but mostly it's just changing the syntax.

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

jQuery class count on a certain table column number

I've been at this for a while and want to know the best way of achieving my goal if anyone has any ideas!
Example:
<table>
<tbody>
<tr>
<td>Hello</td>
<td>Hello (I want to check this column)</td>
</tr>
<tr>
<td>Hello 2</td>
<td class="active">Hello 2 (this column)</td>
</tr>
</tbody>
</table>
jQuery I've got so far (I'm traversing from a clicked element):
var length = $(self).closest("tbody").find("tr").find("td.active").length;
Obviously this gets all the active classes of td, when I only want the second column. I've tried:
var length = $(self).closest("tbody").find("tr").find("td:eq(1).active").length;
This does not work.
Any ideas?
If I'm understanding correctly, you want to get the table cells in the second column (not the first as indicated in the question) which have the class active on them. If that's the case, you can use the following:
var length = $(self).closest('tbody').find('tr').find('td:eq(1)').filter('.active').length;
http://jsfiddle.net/mikemccaughan/g6mnn/
I think your selector isn't doing what you expect it to. I would have expected what you're expecting, but check out this paragraph from the eq() documentation (emphasis mine):
Note that since JavaScript arrays use 0-based indexing, these
selectors reflect that fact. This is why $('.myclass:eq(1)') selects
the second element in the document with the class myclass, rather than
the first. In contrast, :nth-child(n) uses 1-based indexing to conform
to the CSS specification.
So you're going to want to use td:eq(1) without the class selector, then filter your results, and then count them:
var length = $(self).closest("tbody").find("td:eq(1)").filter(".active").length;
Hope that helps!

Referencing an html input element using jQuery

I have the following (repeating) html:
<tr>
<td>Some text</td>
<td><a href="#">Click me<a/></td>
<td><form><input type="hidden" value="4"/></form></td>
</tr>
Using jQuery on the click event of the link I want to retrieve the value of the input element. I have tried all kinds of parents(), children(), nextAll(), prev() combinations but I can not get the value of the input element.
Here is a link to my testing functions. jsFiddle Link
Additionally how would i retrieve the text of the first td element?
Thanks a lot for helping me achieve this.
Michael
You can use parent to get to the td from the a, then next to get to the following td, and then find to get to the input element:
$("a").click(function() {
var value = $(this).parent().next().find("input").val();
});
Here's an updated fiddle.
To get the text from the first td you can take pretty much the same approach, but use prev instead of next.
Also, seeing as you have several repetitions of the HTML snippet, it's probably going to be more efficient to bind the click event handler higher up the DOM tree (maybe you already are, you haven't posted any JS so I don't know):
$("table").on("click", "a", function() {
//Do stuff
});
My usual approach to these things is to use closest to go back to some common container and then find to come back down:
​$('a').click(function() {
var $input = $(this).closest('tr').find('input');
// Do something with $input.val()
});​
Demo: http://jsfiddle.net/ambiguous/Zh6Zk/
The closest/find approach withstands DOM structure changes fairly well so you don't have to worry that much about moving things around in your HTML.
it will give you the input value
$(document).ready(function(e) {
$('.myAnchor').click(function(e){
var parentNode = $(this).parent();
var valueOfInput = $(parentNode).next().children('input').val();
alert(valueOfInput);
});
});
html:
<form>
<table>
<tr>
<td>Some text</td>
<td>Click me</td>
<td><input type=hidden value="4"/></td>
</tr>
</table>
</form>

Is there a jQuery selector/method to find a specific parent element n levels up?

Consider the following HTML. If I have a JSON reference to the <button> element, how can I get a reference to the outer <tr> element in both cases
<table id="my-table">
<tr>
<td>
<button>Foo</button>
</td>
<td>
<div>
<button>Bar</button>
</div>
</td>
</tr>
</table>
<script type="text/js">
$('#table button').click(function(){
//$(this).parent().parent() will work for the first row
//$(this).parent().parent().parent() will work for the second row
//is there a selector or some magic json one liner that will climb
//the DOM tree until it hits a TR, or do I have to code this myself
//each time?
//$(this).????
});
</script>
I know I could special case each condition, but I'm more interested "however deep you happen to be, climb the tree until you find element X" style solution. Something like this, but more jQuery like/less-verbose
var climb = function(node, str_rule){
if($(node).is(str_rule)){
return node;
}
else if($(node).is('body')){
return false;
}
else{
return climb(node.parentNode, str_rule);
}
};
I know about the parent(expr) method, but from what I've seen is allows you filter parents one level up and NOT climb the tree until you find expr (I'd love code example proving me wrong)
The parents function does what you want:
$(this).parents("tr:first");
Also, if you are using jQuery 1.3+ you can use the closest method
$(this).closest("tr");
not jQuery but this options works much better
node.contains( otherNode )
The Node.contains() method returns a Boolean value indicating whether
a node is a descendant of a given node or not
https://developer.mozilla.org/en/docs/Web/API/Node/contains

Categories