I have a table with several rows and columns and a set of search fields. I would like to be able to show / hide the rows that match / don't match the search fields. Each field is related to a column of the table. I have been partly successful in this task, because the filtering is done correctly (as you can see here). However, I would like to fix two things.
s1.localeCompare(s2)
(link here), but it does not work. By the way, no need to worry about uppercase / lowercase typing. I actually take care of it in the original code, but tried to keep it simple here.
The code here:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
table = $("#MI6"); //set table name
search_field = new Object();
///we create it as an object, initially empty
$('.search-key').on('change keyup paste', function () {
search_field['name'] = $( "#name" ).val();
search_field['lastname'] = $("#lastname").val();
search_field['number'] = $("#number").val();
table.find('tr').each(function () {
current_row = $(this); //keep track of the row being checked, iterate through it's cells
var display = 0;
current_row.show();
$(this).find('td').each(function() {
//when we stumble upon the data used as a search criteria
cell_value = $(this).html(); //gets the value of the cell being checked
if (cell_value == search_field[this.id] || search_field[this.id] == '') {
display++;
}
});
if (display < 3) {
current_row.hide(); //if this cell is a match, or we no longer want to use it as a search criteria, the row is displayed
}
});
});
});
</script>
</head>
<body>
<input type="text" id="name" class="search-key" placeholder="name">
<input type="text" id="lastname" class="search-key" placeholder="lastname">
<input type="number" id="number" class="search-key" placeholder="number">
<p></p>
<table id="MI6">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Number</th>
</tr>
<tr>
<td id="name">James</td>
<td id="lastname">Bond</td>
<td id="number">7</td>
</tr>
<tr>
<td id="name">Vesper</td>
<td id="lastname">Lynd</td>
<td id="number">6</td>
</tr>
<tr>
<td id="name">Rene</td>
<td id="lastname">Mathis</td>
<td id="number">5</td>
</tr>
</table>
</body>
</html>
To answer your first question, simply omit the first row of the table from the collection using .not(':first')
:
table.find('tr').not(':first')
In order to do partial string matching, you can use indexOf()
.
The indexOf() method returns the index within the calling String object of the first occurrence of the specified value, starting the search at fromIndex. Returns -1 if the value is not found.
I noticed that you can duplicate ids in your markup, they must be unique.
Your script could be rewritten to be more dynamic with a couple of small changes to the markup:
<td data-input="name">Rene</td>
<td data-input="lastname">Mathis</td>
<td data-input="number">5</td>
You can then use the data-input
to target the corresponding input
. You can combine this with jQuery's filter()
method to return matching rows:
/* $rows = table.find('tr').not(':first') */
$rows.hide().filter(function() {
return $(this).find('td').filter(function() {
var tdText = $(this).text().toLowerCase(),
inputValue = $('#' + $(this).data('input')).val().toLowerCase();
return tdText.indexOf(inputValue) != -1;
}).length == $(this).find('td').length;
}).show();
The above first hides each row, and then filters. Inside of there, each contained td
is filtered, comparing its text against the value of the corresponding input
. If a match is found, the td
is returned. It then checks the number of matching td
elements against the number of td
elements in that row, if they are the same, all fields contain a partial match, and the entire row is returned. Finally, any matching rows are then shown.
This way will allow you to add more inputs, and tds without having to modify the code. You'd just have to set the id
on the input, and add the corresponding data-input
to the td
elements.