Vitalii Romaniv
Vitalii Romaniv

Reputation: 731

How to combine search in table by two input text fields?

My table looks like this:

<table>
   <tr>
      <td>Apple</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Grapes</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Orange</td>
      <td>Orange</td>
   </tr>
</table>

The searching javascript as follows:

var $rows = $('#table tr');
$('#search').keyup(function() {
    var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();

    $rows.show().filter(function() {
        var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
        return !~text.indexOf(val);
    }).hide();
});

Look at this example to understand my problem better:

http://jsfiddle.net/7BUmG/4398/

I filter table rows with the first input field. Then, when I use the second input field, results of first search are not included. How can I fix it?

Upvotes: 2

Views: 2892

Answers (3)

user6213434
user6213434

Reputation:

You can accomplish it using each(). This code will collect the value of each input for each keyup(), then if this value exists in the corresponding td by using indexOf(), it will show the tr which contains this td and hide others, otherwise it will show all tr's

http://jsfiddle.net/7BUmG/4399/

var $rows = $('#table tr'),
    searchVal1,
    searchVal2,
    td1,
    td2;

$('input').keyup(function () {
  searchVal1 = $('#search1').val(),
  searchVal2 = $('#search2').val();

  $rows.each(function (index, tr) {
    td1 = $(tr).find('td:nth-of-type(1)').text().toLowerCase(),
    td2 = $(tr).find('td:nth-of-type(2)').text().toLowerCase();

    if ( (td1.indexOf(searchVal1) != -1) && (td2.indexOf(searchVal2) != -1) ) {
      $(this).show();
    } else {
      $(this).hide();
    }
  });

  if ((searchVal1 === '') && (searchVal2 === '')) {
    $rows.show();
  }
});
body {padding: 20px;}
input {margin-bottom: 5px; padding: 2px 3px; width: 98px;}
td {padding: 4px; border: 1px #CCC solid; width: 100px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="search1" placeholder="Type to search">
<input type="text" id="search2" placeholder="Type to search">
<table id="table">
   <tr>
      <td>Apple</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Grapes</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Orange</td>
      <td>Orange</td>
   </tr>
</table>

Upvotes: 0

Joseph Marikle
Joseph Marikle

Reputation: 78560

Your current logic is a little confused. You are re-showing and re-hiding the filtered items for every search field. What you really want is to filter it all in one go like so:

var $rows = $('#table tr');
$('#search1, #search2').on('input', function() {
    var val1 = $.trim($('#search1').val()).replace(/ +/g, ' ').toLowerCase();
    var val2 = $.trim($('#search2').val()).replace(/ +/g, ' ').toLowerCase();
    
    $rows.show().filter(function() {
        var text1 = $(this).find('td:nth-child(1)').text().replace(/\s+/g, ' ').toLowerCase();
        var text2 = $(this).find('td:nth-child(2)').text().replace(/\s+/g, ' ').toLowerCase();
        return !~text1.indexOf(val1) || !~text2.indexOf(val2);
    }).hide();
});
body {padding: 20px;}
input {margin-bottom: 5px; padding: 2px 3px; width: 98px;}
td {padding: 4px; border: 1px #CCC solid; width: 100px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="search1" placeholder="Type to search">
<input type="text" id="search2" placeholder="Type to search">
<table id="table">
   <tr>
      <td>Apple</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Grapes</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Orange</td>
      <td>Orange</td>
   </tr>
</table>

That's of course assuming non-dynamic number of columns and filter fields. If that's what you're after, you need to check the index rather than hard coding td:nth-child(1) and td:nth-child(2)

Upvotes: 3

Seth M.
Seth M.

Reputation: 156

When you are applying your filter, you are first showing all the rows, negating any previous filtering on them. This is one solution to that problem... it stores the filters and applies both on either input's keyup event, based on your fiddle.

var $rows = $('#table tr');
var filters = { col1: '', col2: ''};
$('#search1').keyup(function() {
    var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
    filters.col1 = val;
    applyFilters();
});
$('#search2').keyup(function() {
    var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
    filters.col2 = val;
    applyFilters();
});
function applyFilters() {
    $rows.show();
  $rows.filter(function() {
        var text = $(this).find('td:nth-child(1)').text().replace(/\s+/g, ' ').toLowerCase();
        return !~text.indexOf(filters.col1);
    }).hide();
  $rows.filter(function() {
    var text = $(this).find('td:nth-child(2)').text().replace(/\s+/g, ' ').toLowerCase();
        return !~text.indexOf(filters.col2);
    }).hide();
};

Upvotes: 4

Related Questions