jQuery search title and contents with accordion

Viewed 49

I wanted to create a live search on the title and the description or content with an accordion. I've seen this post How to search through nested accordion using JS and see if it could help and I've tried it and it works fine.

The problem is I don't think it looks for the title, it only look for the description. I wanted to look at it for both title and description.

HTML

<input type="text" placeholder="Search Keyword Info" class="input-search" id="search-qa">

<div class="container">
  <div class="collapse">
    <div class="collapse__head">
      <label class="qa-question searchable-content" data-category="location"> Where is Test</label>
    </div>
    <div class="collapse__body">
      <div class="collapse__inner">
        <div class="qa-answer" data-category="location">
          <p>Qweeee not a description.</p>
        </div>
      </div>
    </div>
  </div>
  <div class="collapse">
    <div class="collapse__head">
      <label class="qa-question searchable-content" data-category="location"> What is a Test</label>
    </div>
    <div class="collapse__body">
      <div class="collapse__inner">
        <div class="qa-answer" data-category="location">
          <p>Lorem Ips</p>
        </div>
      </div>
    </div>
  </div>
  <div class="collapse">
    <div class="collapse__head">
      <label class="qa-question searchable-content" data-category="location"> Who is Test</label>
    </div>
    <div class="collapse__body">
      <div class="collapse__inner">
        <div class="qa-answer" data-category="location">
          <p>Dolor it</p>
        </div>
      </div>
    </div>
  </div>
</div>

JS

$("#search-qa").on('keyup', function() {

  let searchText = $(this).val().toLowerCase();

  $(".collapse *").each(function() {
  
    let text = $(this).immediateText().toLowerCase();

    if (text.indexOf(searchText) == -1) {
      $(this).parents('.collapse').addClass('hidden');
    }
    else {
      $(this).parents('.collapse').removeClass('hidden');
    }
  });

});

$.fn.immediateText = function() {
  return this.contents().not(this.children()).text();
};

Fiddle: https://jsfiddle.net/idonthaveagirlfriend/3con2p4x/13/

Thanks for the help!

1 Answers

The logic is already searching in both the titles and descriptions of each collapsible section.

The issue is due to the fact you add or remove the hidden class in every iteration of the loop through the child elements. As such, you could remove the class when a match is found in one child but then the class is added to hide the parent again when there is no match in the next child.

To fix this you can amend you logic so that you hide everything before the search starts and unhide only when a match is found within the loop. Try this:

jQuery($ => {
  $("#search-qa").on('keyup', function() {
    let searchText = $(this).val().toLowerCase().trim();
    $('.collapse').addClass('hidden', searchText.length > 0); // hide all elements when a search starts

    $(".collapse *").each(function() {
      let $child = $(this);
      let $collapse = $child.closest('.collapse');
      let text = $child.immediateText().toLowerCase().trim();

      if (text.indexOf(searchText) !== -1)
        $collapse.removeClass('hidden'); // show the current collapse container when a match is found
    });
  });
})

$.fn.immediateText = function() {
  return this.contents().not(this.children()).text();
};
.collapse {
  border: 1px solid currentColor;
  margin: 10px 0;
  -webkit-transition: background 0.2s ease-in;
  -moz-transition: background 0.2s ease-in;
  -o-transition: background 0.2s ease-in;
  transition: background 0.2s ease-in;
}

.collapse__head {
  font-size: 20px;
  font-weight: 700;
  position: relative;
  cursor: pointer;
}

.collapse__body {
  max-height: 0;
  overflow: hidden;
  transition: all 300ms ease;
}

.hidden {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<input type="text" placeholder="Search Keyword Info" class="input-search" id="search-qa">

<div class="container">
  <div class="collapse">
    <div class="collapse__head">
      <label class="qa-question searchable-content" data-category="location"> Where is Test</label>
    </div>
    <div class="collapse__body">
      <div class="collapse__inner">
        <div class="qa-answer" data-category="location">
          <p>Qweeee not a description.</p>
        </div>
      </div>
    </div>
  </div>
  <div class="collapse">
    <div class="collapse__head">
      <label class="qa-question searchable-content" data-category="location"> What is a Test</label>
    </div>
    <div class="collapse__body">
      <div class="collapse__inner">
        <div class="qa-answer" data-category="location">
          <p>Lorem Ips</p>
        </div>
      </div>
    </div>
  </div>
  <div class="collapse">
    <div class="collapse__head">
      <label class="qa-question searchable-content" data-category="location"> Who is Test</label>
    </div>
    <div class="collapse__body">
      <div class="collapse__inner">
        <div class="qa-answer" data-category="location">
          <p>Dolor it</p>
        </div>
      </div>
    </div>
  </div>
</div>

Related