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();
});
4
  • At "Term1 and Term2 and Term3 etc?" , is requirement to show all "Term1 and Term2 and Term3 etc?" ? Commented Mar 19, 2015 at 5:53
  • yes, the requirement is to show only results that contain all terms, not just the last one entered Commented Mar 19, 2015 at 5:59
  • Show entire tr , or only td containing matched term ? Are td initally hidden ? Commented Mar 19, 2015 at 6:01
  • Here jsfiddle.net/L83j3p79/4 Commented Mar 19, 2015 at 6:21

3 Answers 3

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();
Sign up to request clarification or add additional context in comments.

1 Comment

Brilliant, thanks! I never though of checking for what the array didn't have :)
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();

Comments

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.