Reputation: 3611
Title might be a bit confusing, but this is the best I could come up with.
I need to find all tr
elements which contains td
elements matching the filter criteria provided.
Here is my sample,
<tr class="row" id="1">
<td class="philips">PHILIPS</td>
<td class="h4">H4</td>
<td class="lamp">Lamp<td>
</tr>
<tr class="row" id="2">
<td class="philips">PHILIPS</td>
<td class="h5">H5</td>
<td class="bulb">Bulb<td>
</tr>
<tr class="row" id="3">
<td class="neglin">NEGLIN</td>
<td class="w5w">W5W</td>
<td class="tube">Tube<td>
</tr>
<tr class="row" id="4">
<td class="philips">PHILIPS</td>
<td class="h4">H4</td>
<td class="bulb">Bulb<td>
</tr>
<tr class="row" id="5">
<td class="osram">OSRAM</td>
<td class="hb3">HB3</td>
<td class="tube">Tube<td>
</tr>
<tr class="row" id="6">
<td class="neglin">NEGLIN</td>
<td class="w5w">W5W</td>
<td class="lamp">Lamp<td>
</tr>
If I pass filter[0]
as 'phillips', the result return tr
with id
Then if I pass second filter; filter[1]
as 'h4', the result should be filtered down to
I have tried this question.
Which has this answer.
$('tr')
.has('td:nth-child(1):contains("Audi")')
.has('td:nth-child(2):contains("red")')
.doSomeThing();
But, I want my filters to be applied dynamically. How would I be able to insert a 3rd has
function?
I don't want to go the if-else
or switch-case
way, if this is possible with out them.
Upvotes: 1
Views: 1077
Reputation: 26
You can try this.
<script type="text/javascript">
$(document).ready(function () {
var result = filter([".philips", ".h4"]);
alert(result);
var result_2 = filter([".philips"]);
alert(result_2);
});
function filter(params) {
var select = "tr";
for (var i = 0; i < params.length; i++) {
select += ":has(" + params[i] + ")";
}
return $(select).map(
function () {
return $(this).attr('id');
}
).get();
}
</script>
Upvotes: 1
Reputation: 12142
You can supply your filter as a string:
var filter = ".philips, .h4";
$("tr").has("td").has(filter).map(function() { return this.id; });
// returns ["1", "2", "4"]
and if you want the elements then obviously leave the map off:
$("tr").has("td").has(filter);
// returns array of <tr>
Edit: Just noticed you want recursive filtering so change the filter to use sibling selector ~
.
var filter = ".philips ~ .h4";
// returns ["1", "4"]
So if you want a third level then just:
var filter = ".philips ~ .h4 ~ .bulb";
// returns ["4"]
Upvotes: 0
Reputation: 558
if you have an array of filters needed, iterate that array and pass the filter string to the has?
var filters = ['PHILIPS', 'H4', 'Bulb']
var result = $('tr');
for(var i = 0; i < filters.length; i++){
var nchild = i+1;
result = result.has('td:nth-child('+nchild+'):contains("+'filters[i]'+")');
}
edit to your needs of course, but this way you can take user input, compile that into the needed array and then iterate whatever is in the array to filter down results.
Upvotes: 1
Reputation: 1244
You should wrap the $.has() into a separate function (I've just used jquery's easy extensions supports) which will expose the usage as a composite function chain via javascript's syntax...
$( document ).ready(function() {
$('tr')
.nthFilter('td:nth-child(1):contains("PHILIPS")')
.nthFilter('td:nth-child(2):contains("H4")')
.nthFilter('td:nth-child(3):contains("Bulb")')
.css("background-color", "red");
});
jQuery.fn.extend({
nthFilter: function(filter) {
return $(this).has(filter);
}
});
I've put together a small jsfiddle for you to fiddle with :)
Upvotes: 0