javascripthtmlcssecmascript-6search-box

How to hide answers before searching


I have used the code below to filter div elements but I want it to only show the results after typing something in the search bar. When nothing is searched/typed in the search box till then nothing is shown. Hope you are getting what I am saying. I want it to only show the results when someone enters anything.

const searchBar = document.forms['search-books'].querySelector('input');
searchBar.addEventListener('keyup', function(e) {
  const term = e.target.value.toLocaleLowerCase();
  const books = list.getElementsByTagName('h5');
  Array.from(books).forEach(function(books) {
    const title = book.firstElementChild.textContent;
    if (title.toLowerCase().indexOf(term) != -1) {
      book.style.display = 'block';
    } else {
      book.style.display = 'none';
    }
  })
})
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />

<form id="search-books">
  <input type="text" placeholder="Search a book ... ">
</form>
<div class="container">
  <div class="row list-single">
    <div class="col-2"><img src="https://images.gr-assets.com/books/1447303603s/2767052.jpg" /></div>
    <div class="col-10">
      <h5> The Hunger Games</h5>
      <a href="The-Hunger-Games.html">Learn</a>
    </div>
  </div>
  <br>
  <div class="row list-single">
    <div class="col-2"><img src="https://images.gr-assets.com/books/1507396732s/2.jpg" /></div>
    <div class="col-10">
      <h5>Harry Potter</h5>
      <a href="Harry-Potter.html">Learn</a>
    </div>
  </div>


Solution

  • There are multiple ways to do this. I will go with one of the possible approaches.

    First, you need to hide all your list element with CSS selector in the first place like this:

    .row.list-single {
       display: none;
    }
    

    Then you need to check whether your search input is filled with words or not, if not you need to hide all the elements. So you can simply do that like this:

    if (!term) {
      const bookList = document.querySelectorAll('.list-single')
      Array.from(bookList).forEach(function(list) {
        list.style.display = 'none';
      })
    }
    

    That's all that you need to do. But you made some mistakes in your code and I fixed them on the fly.

    So your final code should be something like this (When someone searches for existing items item will be shown e.g h will show both results):

    const searchBar = document.forms['search-books'].querySelector('input');
    searchBar.addEventListener('keyup', function(e) {
      const term = e.target.value.toLocaleLowerCase();
      if (!term) {
        const bookList = document.querySelectorAll('.list-single')
        Array.from(bookList).forEach(function(list) {
          list.style.display = 'none';
        })
      } else {
        const books = document.getElementsByTagName('h5');
        Array.from(books).forEach(function(book) {
          const title = book.textContent;
          if (title.toLowerCase().indexOf(term) != -1) {
            book.closest('.list-single').style.display = 'block';
          } else {
            book.closest('.list-single').style.display = 'none';
          }
        })
      }
    })
    .row.list-single {
      display: none;
    }
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
    
    <form id="search-books">
      <input type="text" placeholder="Search a book ... " />
    </form>
    <div class="container">
      <div class="row list-single">
        <div class="col-2"><img src="https://images.gr-assets.com/books/1447303603s/2767052.jpg" /></div>
        <div class="col-10">
          <h5> The Hunger Games</h5>
          <a href="The-Hunger-Games.html">Learn</a>
        </div>
      </div>
      <br>
      <div class="row list-single">
        <div class="col-2"><img src="https://images.gr-assets.com/books/1507396732s/2.jpg" /></div>
        <div class="col-10">
          <h5>Harry Potter</h5>
          <a href="Harry-Potter.html">Learn</a>
        </div>
      </div>


    If you are looking for a more elegant and efficient way you can do all the conditions in same place as below:

    const searchBar = document.forms['search-books'].querySelector('input');
    const books = document.getElementsByTagName('h5');
    searchBar.addEventListener('keyup', function(e) {
      const term = e.target.value.toLocaleLowerCase();
      Array.from(books).forEach(function(book) {
        const title = book.textContent;
        if (term && title.toLowerCase().indexOf(term) != -1) {
          book.closest('.list-single').style.display = 'block';
        } else {
          book.closest('.list-single').style.display = 'none';
        }
      })
    })
    .row.list-single {
      display: none;
    }
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
    
    <form id="search-books">
      <input type="text" placeholder="Search a book ... " />
    </form>
    <div class="container">
      <div class="row list-single">
        <div class="col-2"><img src="https://images.gr-assets.com/books/1447303603s/2767052.jpg" /></div>
        <div class="col-10">
          <h5> The Hunger Games</h5>
          <a href="The-Hunger-Games.html">Learn</a>
        </div>
      </div>
      <br>
      <div class="row list-single">
        <div class="col-2"><img src="https://images.gr-assets.com/books/1507396732s/2.jpg" /></div>
        <div class="col-10">
          <h5>Harry Potter</h5>
          <a href="Harry-Potter.html">Learn</a>
        </div>
      </div>