1

I have a filter function that needs to check an array of elements against the value of an input field. I originally used this solution, but it reassesses all results when a second or third term is entered.

Here's a Fiddle of my situation.

Currently, if I enter 'fish', it will return only the row containing 'fish', so far so good. If I also enter 'yellow', so 'fish yellow', it returns both 'Fish' and 'Parrot', when I actually want it to still only return 'Fish', as it's the only row that contains all terms in the input field.

So instead of filtering like this:

input value = "Term1 Term2 Term3"

  1. Term1, start again, then
  2. Term2, start again, then
  3. Term3, start again...

Is there a way to filter the 'jo' array like this:

  1. Term1, then
  2. Term1 and Term2, then
  3. Term1 and Term2 and Term3 etc?

Below, I tried pushing the number of words in the input field into another array, then trying to get it to loop sequentially through all the words, but it wasn't working :(

HTML

<input id="filter-field" placeholder="Search" type="text" />

<table cellspacing="0" cellpadding="0" >
    <thead>
        <tr>
            <th>Pet</th>
            <th>Colour</th>
        </tr>
    </thead>
    <tbody>
        <tr>    
            <td>cat</td>
            <td>white</td>
        </tr>
        <tr>
            <td>dog</td>
            <td>black</td>
        </tr>
        <tr>
            <td>parrot</td>
            <td>yellow</td>
        </tr>
        <tr>
            <td>fish</td>
            <td>yellow</td>
        </tr>
        <tr>
            <td>hamster</td>
            <td>black</td>
        </tr>
    </tbody>
</table>

jQuery

$("#filter-field").on('input', function() {

        // Split the current value of searchInput
        var data = this.value.split(" "),
            inputLength = $("#filter-field").val().length;

        // Create a jquery object of the rows
        var jo = $("table > tbody").find("tr");

        if (this.value == "") {
            jo.show();
            return;
        }

        // Hide all the rows
        jo.hide();

        jo.filter(function() {
            var $t = $(this),
                textField = $('#filter-field').val().split(" "),
                wordCount = textField.length - 1, // Get length of array, then subtract 1 so 'word #1' matches 'position 0' in array
                wordCounter = [];

            // I wanted this to end up as [1, 2, 3, 4 etc] to somehow check each word against 'jo', but each .push() simply adds 1 to the first array value
            wordCounter.push(wordCount);

            // I want this to check for 'word A', then if I enter further words, 'word A and word B' etc
            if ($t.is(":contains('" + textField[wordCounter] + "')")) {
                return true;
            } else {
                return false;
            }

        }).show();
});
Community
  • 1
  • 1
Timmah
  • 1,283
  • 2
  • 10
  • 26

3 Answers3

4

The way you are approaching the problem looks awkward. I think something like this should work fine:

        jo.filter(function() {
            var $t = $(this),
                textField = $('#filter-field').val().split(" ");

            for(var i=0; i<textField.length; i++)
            {
                if (!$t.is(":contains('" + textField[i] + "')"))
                {
                    return false;
                }
            }
            return true;

        }).show();
Michael Holman
  • 901
  • 1
  • 10
  • 26
0

I think you should use a match example of your original code https://jsfiddle.net/L83j3p79/4/

jo.filter(function() {
         var textField = $.trim($('#filter-field').val()).split(" ");
         var theSearch = textField.join("|");
         return (this.textContent || this.innerText).match(theSearch);
}).show();
lukesUbuntu
  • 527
  • 2
  • 12
  • 22
0

Try

var input = $("#filter-field")
,  tr = $("table tbody tr");

input.on("input", function(e) {
  var val = e.target.value
  , term = /\s/.test(val) ? val.split(/\s/) : [val]
  , res = $.map(tr.find("td"), function(elem) {
            var el = $(elem) || elem;
            return term.length === 1 
                   ? $.inArray(el.html(), term) !== -1 
                     && el.parent().show() 
                   : $.inArray(el.html(), term) !== -1 
                     && $.inArray(el.siblings(el.nodeName).html(), term) !== -1 
                     ? el.parent().show() 
                     : el.parent().hide() && null
  }).filter(Boolean);
  if (!val.length) { tr.hide() };
});
table tbody tr {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<input id="filter-field" placeholder="Search" type="text" />

<table cellspacing="0" cellpadding="0">
  <thead>
    <tr>
      <th>Pet</th>
      <th>Colour</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>cat</td>
      <td>white</td>
    </tr>
    <tr>
      <td>dog</td>
      <td>black</td>
    </tr>
    <tr>
      <td>parrot</td>
      <td>yellow</td>
    </tr>
    <tr>
      <td>fish</td>
      <td>yellow</td>
    </tr>
    <tr>
      <td>hamster</td>
      <td>black</td>
    </tr>
  </tbody>
</table>
guest271314
  • 1
  • 15
  • 104
  • 177