I have an id for a <tr id="tagTR">
Given the above, is it possible to find the next input:text
element regardless of any other mark up in between . Is there a jQuery selector that I can use for this scenario?
For example :
<tr id="tagTR">
</tr>
<tr id="tagRed">
<td> </td>
</tr>
<div>
<tr>
<td>
<input> // This is what I want to get to.
</td>
</tr>
</div>
I thought this question was very interesting. It seems others are reading this as, find the next input among siblings. But I read it as - find me the next input no matter what. I don't know if its in a sibling, a parent or a parent's sibling. This is what I came up with based on feedback I received from this question.
http://jsfiddle.net/GesSj/1
//assume you know where you are starting from
var $startElement = $('#foo');
//get all text inputs
var $inputs = $('input[type=text]');
//search inputs for one that comes after starting element
for (var i = 0; i < $inputs.length; i++) {
if (isAfter($inputs[i], $startElement)) {
var nextInput = $inputs[i];
alert($(nextInput).val());
}
}
//is element before or after
function isAfter(elA, elB) {
return ($('*').index($(elA).last()) > $('*').index($(elB).first()));
}
Check it out: moved this into a more complete question and answer
Based on the awesome answer by @mrtsherman, I wrote this more complete solution:
(function( $ ){
$.fn.findNext = function(sel) {
var $result = $(sel).first();
if ($result.length <= 0) {
return $result;
}
$result = [];
var thisIndex = $('*').index($(this));
var selIndex = Number.MAX_VALUE; // Number.MAX_SAFE_INTEGER is not yet fully supported
$(sel).each(function(i,val){
var valIndex = $('*').index($(val));
if (thisIndex < valIndex && valIndex < selIndex) {
selIndex = valIndex;
$result = $(val);
}
});
return $result;
};
})( jQuery );
Then you can use it as this:
$('#tagTR').findNext('input');
I would submit a PR for this on jQuery lib if I knew my code was properly optimized and if it was okay by Mr T Sherman there, meaning I think this should be a core method on jQuery! :P
@Cawas - nice solution, but I suggest to use it not excessive, because of $('*')
is expensive ;-)
Regardless of that, I extended it for my needs:
(function( $ ){
$.fn.findNextOverall = function(sel, returnItselfIfMatched) {
if(returnItselfIfMatched && $(this).is(sel)) return $(this);
var $result = $(sel).first();
if ($result.length <= 0) {
return $result;
}
$result = [];
var thisIndex = $('*').index($(this));
var selIndex = Number.MAX_SAFE_INTEGER;
$(sel).each(function(i,val){
var valIndex = $('*').index($(val));
if (thisIndex < valIndex && valIndex < selIndex) {
selIndex = valIndex;
$result = $(val);
}
});
return $result;
};
})( jQuery );
So if returnItselfIfMatched
is set true
it returns itself, if it matches the selector itself. Useful, if you don't know, which element is calling and you are searching for exactly itself.
You cannot have a div
tag in between TR's
. It is not a valid markup.
To find the input
element from the referred tr
you can try this.
$('#tagTR').nextAll().filter(function(){
return $(this).find('input:text').length > 1;
}).find('input');
You can use "next":
$("#tagTR").next("input")