1

I can't figure out something that is probably quite simple to do. I have a grid with cards that look like this:

<div class="card">
  <img src="data:image/jpg;base64,{{ books[book]['cover']}}" class="card-img-top" alt="...">
  <div class="card-img-overlay">
    <span class="title"><h5 class="bg-dark text-white">{{ book }}</h5></span>
    <span class="author"><h5 class="bg-dark text-white author">{{ books[book]['author'] }}</h5>
  </div>
</div>

I have an input field called search-authors and want to hide cards that do not contain whatever the value of search-authors is.

I'm trying to use this:

            $("#search-authors").on("keyup", function() {
              var value = $(this).val().toLowerCase();
                $(".card *").filter(function() {
                  $(".card").css('display', 'none')
                  .filter(':contains(' + value + ')')
                  .css('display', 'block');
                });
            });

This isn't working the way I expect it to. For example, typing just c shows only cards which contain c but typing co hides cards that contain co and did show up correctly typing just c.

Any pointers would be greatly appreciated!

Thanks

Foobarian
  • 13
  • 2

1 Answers1

0

There's a couple of issues in your code.

  • You need to select the .card elements, not their child elements, and hide/show them directly.
  • Use the input event instead of keyup. The former allows people to paste content in with the mouse, the latter does not.
  • You don't need to nest the filter() calls.
  • You're using filter() like a loop, which is unnecessary. Call filter() directly on the .card collection and update the matching elements from there.
  • :contains is case-sensitive by default, so converting the input to lowercase isn't enough. However, you can implement your own case-insensitive version of :contains (credit @HighwayOfLife in this answer)

With all that said, try this:

$.expr[':'].icontains = (a, i, m) => $(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;

$("#search-authors").on("input", e => {
  $(".card").hide().filter(`:icontains(${e.target.value.trim()})`).show();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<input type="text" id="search-authors" />
<div class="card">
  <img src="data:image/jpg;base64,{{ books[book]['cover']}}" class="card-img-top" alt="...">
  <div class="card-img-overlay">
    <span class="title"><h5 class="bg-dark text-white">ABC Book 1</h5></span>
    <span class="author"><h5 class="bg-dark text-white author">DEF Author 1</h5></span>
  </div>
</div>
<div class="card">
  <img src="data:image/jpg;base64,{{ books[book]['cover']}}" class="card-img-top" alt="...">
  <div class="card-img-overlay">
    <span class="title"><h5 class="bg-dark text-white">ABC Book 2</h5></span>
    <span class="author"><h5 class="bg-dark text-white author">DEF Author 2</h5></span>
  </div>
</div>
<div class="card">
  <img src="data:image/jpg;base64,{{ books[book]['cover']}}" class="card-img-top" alt="...">
  <div class="card-img-overlay">
    <span class="title"><h5 class="bg-dark text-white">UVW Book 1</h5></span>
    <span class="author"><h5 class="bg-dark text-white author">XYZ Author 1</h5></span>
  </div>
</div>
<div class="card">
  <img src="data:image/jpg;base64,{{ books[book]['cover']}}" class="card-img-top" alt="...">
  <div class="card-img-overlay">
    <span class="title"><h5 class="bg-dark text-white">UVW Book 2</h5></span>
    <span class="author"><h5 class="bg-dark text-white author">XYZ Author 2</h5></span>
  </div>
</div>
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • 1
    Thanks for your quick and excellent reply! It solved my issue and I got a better understanding of how things work! :-) – Foobarian Jan 27 '22 at 13:42