Using jQuery to filter a table from multiple select elements
I want to filter a table using jQuery hide/show based on what the user selects from multiple select elements.
I want the user to be able to select multiple values from 1, 2 or 3 of the select elements. So maybe they'll select 2 trainers, 1 recruit and 1 status, or maybe just 1 trainer. Planning on creating a function that will run when the user clicks any of the options.
The way I see it, each select element will have an array of values that the user has selected. So I'll need to loop through each array and compare it to the text in that specific column. Would be easy enough if the options were from only 1 select element. But since it could be 1, 2 or all 3, I'm having trouble getting my head around it.
Any help would be GREATLY appreciated.
Table:
<table id="reportsTable">
<thead>
<th>Report Number</th>
<th>Date</th>
<th>Name</th>
<th>Trainer</th>
<th>Status</th>
</thead>
<tbody>
<tr>
<td>12345-1</td>
<td>05/01/2011</td>
<td>First Recruit</td>
<td>First Trainer</td>
<td>Complete</td>
</tr>
<tr>
<td>12345-2</td>
<td>05/02/2011</td>
<td>First Recruit</td>
<td>Second Trainer</td>
<td>In Progress</td>
</tr>
<tr>
<td>54321-1</td>
<td>05/03/2011</td>
<td>Second Recruit</td>
<td>First Trainer</td>
<td>Created</td>
</tr>
</tbody>
</table>
Selects:
<select multiple="multiple" name="trainerFilter">
<option value="firsttrainer">First Trainer</option>
<option value="secondtrainer">Second Trainer</option>
</select>
<select multiple="multiple" name="recruitFilter">
<option value="firstrecruit">First Recruit</option>
<option value="secondrecruit">Second Recruit</option>
</select>
<select multiple="multiple" name="statusFilter">
<option value="created">Created</option>
<option value="inprogress">In Progress</option>
<option value="complete">Complete</option>
</select>
Looks like I can't post an answer to my question for 8 hours but this is what I came up with thanks to @Spencer Ruport. It ended up being a lot more convoluted than I expected thanks to having to account for all possible entries. The user could select something from the first select element, nothing from the second, and maybe 2 from the third. Or maybe the user doesn't select anything from the first and 2 from the second. For any given input, there may be 6+ filters than need to be applied.
I'm sure there's a better way than this, and it looks like @Alison may have linked to one, but it works.
function filterReports() {
$('.report').hide(); //Set all rows to hidden.
trainerVals = $('#trainerFilter').val();
recruitVals = $('#recruitFilter').val();
statusVals = $('#statusFilter').val();
if (trainerVals) { //Check if any trainers are selected.
$.each(trainerVals, function(index, trainer) {
filtered = false;
classString = '';
classString += '.' + trainer;
if (recruitVals) { //Check if trainers and recruits are selected.
$.each(recruitVals, function(index, recruit) {
filtered = false;
secondString = '';
secondString = classString + '.' + recruit; //Concat to a new string so we keep the old one intact.
if (statusVals) { //Check if trainers, recruits and statuses are selected.
$.each(statusVals, function(index, status) {
filtered = false;
finalString = '';
finalString += secondString + '.' + status; //Again concat to a new string.
$(finalString).show();
filtered = true; //By setting filtered to true, we only run the show once.
});
}
if (!filtered) { //If trainers and recruits are selected, but not a status, we need to apply that filter.
$(secondString).show();
filtered = true;
}
});
}
if (!filtered && statusVals) { //If only trainers and statuses are selected, go through those.
$.each(statusVals, function(index, status) {
filtered = false;
finalString = '';
finalString += classString + '.' + status;
$(finalString).show();
filtered = true;
});
}
if (!filtered) { //If only trainers are selected, apply that filter.
$(classString).show();
filtered = true;
}
});
}
if (!filtered && recruitVals) { //If trainers are not selected, by recruits are, run through the recruits.
$.each(recruitVals, function(index, recruit) {
classString = '';
classString += '.' + recruit;
if (statusVals) { //Check if recruits and statuses are selected
$.each(statusVals, function(index, status) {
finalString = '';
finalString += classString + '.' + 开发者_JS百科status;
$(finalString).show();
filtered = true;
});
}
if (!filtered) { //If only recruits are selected, apply that filter.
$(classString).show();
filtered = true;
}
});
}
if (!filtered && statusVals) { //If both trainers and recruits are not selected, but statuses are, run through those.
$.each(statusVals, function(index, status) {
classString = '';
classString += '.' + status;
$(classString).show();
filtered = true;
});
}
if (!filtered) {
//No filters selected.
}
$("tr").removeClass("even"); //Remove current zebra striping.
$("tr:visible:even").addClass("even"); //Add zebra striping only for rows that are visible.
}
Take a look at the jQuery Datatables plug-in. It makes manipulating an HTML table a snap. With some simple setting changes, you can easily do what you're looking for (and more.)
Make sure to check out the example on filtering using select elements
This is pretty simple to do using multiple classes (I usually call them markers when they're not being used for styles.)
<table>
<thead>
<th>Report Number</th>
<th>Date</th>
<th>Name</th>
<th>Trainer</th>
<th>Status</th>
</thead>
<tbody>
<tr class="obj_first_recruit obj_first_trainer obj_complete obj_row_item">
<td>12345-1</td>
<td>05/01/2011</td>
<td>First Recruit</td>
<td>First Trainer</td>
<td>Complete</td>
</tr>
<tr class="obj_first_recruit obj_second_trainer obj_in_progress obj_row_item">
<td>12345-2</td>
<td>05/02/2011</td>
<td>First Recruit</td>
<td>Second Trainer</td>
<td>In Progress</td>
</tr>
<tr class="obj_second_recruit obj_first_trainer obj_created obj_row_item">
<td>54321-1</td>
<td>05/03/2011</td>
<td>Second Recruit</td>
<td>First Trainer</td>
<td>Created</td>
</tr>
</tbody>
</table>
Then anytime you want to filter just concatenate all the corresponding markers with periods for example:
$(".obj_row_item").hide();
$(".obj_first_recruit.obj_second_trainer.obj_in_progress").show();
For simplicity's sake you can make the values of the dropdowns correspond to the marker names making your statement look something like:
$("." + $("#dropdown1").val() + "." + $("#dropdown2").val() + "." + $("#dropdown3").val()).show();
精彩评论