2

I have a nested list of checkboxes which I need to filter them down based on textbox input compared to the label's value. The list looks like this but a lot larger:

enter image description here

Fiddle: https://jsfiddle.net/y9qqgjp5/

However, I'm having trouble with the nested part of this. As I have it now, if you go to search a user (2nd level item), the parent becomes hidden because it doesn't match and thus makes the children hidden, as well. It works fine with filtering on a parent.

Here's the simplified structure I'm filtering on.

HTML:

<input type="text" id="filter" />
<span class="checkbox-list">
<ul>
    <li>
        <label>Item1</label>
        <ul>
            <li>
                <label>Item2</label>
            </li>
            <li>
                <label>Item3</label>
            </li>
            <li>
                <label>Item4</label>
            </li>
            <li>
                <label>Item5</label>
            </li>
        </ul>
    </li>
    <li>
        <label>Item6</label>
    </li>
    <li>
        <label>Item7</label>
        <ul>
            <li>
                <label>Item4</label>
            </li>
            <li>
                <label>Item8</label>
            </li>
        </ul>
    </li>
</ul>
</span>

JQuery:

$('#filter').keyup(function() {
  var valThis = $(this).val().toLowerCase();
  if (valThis == "") {
    $('.checkbox-list > ul > li > label').parent().show();
  } else {
    $('.checkbox-list > ul > li > label').each(function() {
      var text = $(this).text().toLowerCase();
      (text.indexOf(valThis) >= 0) ? $(this).parent().show(): $(this).parent().hide();
    });
  };

  if (valThis == "") {
    $('.checkbox-list > ul > li > ul > li > label').parent().show();
  } else {
    $('.checkbox-list > ul > li > > ul > li > label').each(function() {
      var text = $(this).text().toLowerCase();
      (text.indexOf(valThis) >= 0) ? $(this).parent().show(): $(this).parent().hide();
    });
  };
});

Any help is appreciated. I can't wrap my head around the nested part of this.

1
  • So what did you want to happen? If I search for item2, it shows the parent and item2 itself? Commented Feb 8, 2018 at 16:20

1 Answer 1

5

Try using parents()

var labels = $('label');  // cache this for better performance

$('#filter').keyup(function() {
  var valThis = $(this).val().toLowerCase();
  
  if (valThis == "") {
    labels.parent().show();          // show all lis
  } else {
    labels.each(function() {
      var label = $(this);                    // cache this
      var text = label.text().toLowerCase();
      if (text.indexOf(valThis) > -1) {
        label.parents('li').show()           // show all li parents up the ancestor tree
      } else {
       label.parent().hide();                // hide current li as it doesn't match
      }
    });
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="filter" />
<span class="checkbox-list">
<ul>
    <li>
        <label>Item 1</label>
        <ul>
            <li>
                <label>Item 12</label>
            </li>
            <li>
                <label>Item3</label>
            </li>
            <li>
                <label>Item4</label>
            </li>
            <li>
                <label>Item5</label>
            </li>
        </ul>
    </li>
    <li>
        <label>Item6</label>
    </li>
    <li>
        <label>Item7</label>
        <ul>
            <li>
                <label>Item4</label>
            </li>
            <li>
                <label>Item8</label>
            </li>
        </ul>
    </li>
</ul>
</span>

Sign up to request clarification or add additional context in comments.

2 Comments

This works for what I specified. However, I did notice I don't like the functionality of one part: When it matches a parent, all of the children should show. I'm not sure if that warrants another question or if it's an easy change... let me know. I'll give it a shot myself, too.
That's probably a new question as it would be quite a big change, you wouldn't be able to use an each like above as you may hide children again after they are shown

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.