user2271851
user2271851

Reputation: 23

Issues with code for a simple on page search

I am trying to build a simple on page search that uses event listeners to look at a containers data and then hides that whole container if it doesn't have the required information.

So far I have:


    // get search element
    let searchInput = document.getElementById ('searchInput'); 

    // add event listener
    searchInput.addEventListener ('keyup', searchPage);


    function searchPage(){
      //search input detection
      let searchValue = document.getElementById('searchInput').value;

      //set parameters to search from
      let  parent = document.getElementById('product-container');
      let child = parent.getElementsByTagName('span');

          for(let i = 0;i < child.length;i++){

            let a = child[i];

            if(a.innerHTML.indexOf(searchValue) >= -1) {

              child[i].parentNode.style.display = '';

            } else {

              child[i].parentNode.style.display = 'none';

            };

          };
    };

But this only acts on the first product-container it finds, there are 5 such containers on the page.

How do I make this look through all containers, but hide the ones that don't contain any of the information typed in the search bar.

I am getting products from an API so using html replace to add to the following template:


    <script id="template" type="text/template">
        <div class="product">
          <div class="product--header">{{ type }}</div>
          <div class="product--image"><img src="../app/assets/images/no-image.png" alt="no image"> </div>
          <div class="product--information" id="product--information">
            <div class="product--title"><span>{{ name }}</span></div>
            <!--This is just a place holder we would house the prices here if they were on the API -->
            <div class="product--price">£55</div>
            <div class="product--brand"><strong>Brand:</strong><span> {{ brand }}</span></div>
            <div class="product--colour"><strong>Colour:</strong><span> {{ colour }}</span></div>
            <div class="product--sizes">
              <select>
                  <option value="" disabled selected>Select Size </option>
                  {{ options }}
              </select>
            </div>
            <div class="product--description"><strong>Description:</strong><br><div class="product--description__content"><span> {{ description }} </span></div></div>
            <div class="product--code"><strong>Product ID:</strong><span> {{ productid }}</span></div>
            <div class="product--buttons">
              <button class="btn--buy" aria-label="Add to Basket">Add to basket</button>
              <button class="btn--save" aria-label="Save for Later">Save for later</button>     
            </div>
            <button class="product--add-to-wishlist" aria-label="Add to Wishlist"><i class="fas fa-heart"></i></button>
          </div>
        </div>
    </script>

The search box code is as follows:

    <input type="text" name="search" id="searchInput" placeholder="Enter Search...">

and the code that the template goes into is:

    <div id="product-container">
      <div class="featured"></div>
      <div class="products"></div>
    </div>

Upvotes: 2

Views: 116

Answers (1)

Gardelin
Gardelin

Reputation: 1071

Because you have multiple product containers, use document.getElementsByClassName() instead of document.getElementById() and provide product-container class as argument.

let searchInput = document.getElementsByClassName ('container'); 

You need to modify searchPage() method. Instead of using document to find searchValue and parent use this.

let searchValue = this.getElementsByClassName('searchInput')[0].value;
let parent = this.getElementsByClassName('container')[0];

Please, add HTML code.

EDIT: If I understand correctly you have one search input which will search multiple product containers. Here is one simple example, which you can easily apply to your problem.

HTML:

<input type="text" name="search" id="searchInput" placeholder="Enter Search...">

<div class="product-container">
  <span class="product">Kiwi</span>
  <p>Kiwi description</p>
</div>

<div class="product-container">
  <span class="product">Banana</span>
  <p>Banana description</p>
</div>

<div class="product-container">
  <span class="product">Apple</span>
  <p>Apple description</p>
</div>

JS:

    let searchInput = document.getElementById ('searchInput'); 
    searchInput.addEventListener ('keyup', searchPage);

    function searchPage(){
      let searchValue = this.value.toUpperCase();
      let products = document.getElementsByClassName('product');

          for(let i = 0; i < products.length; i++) {
            console.log(products[i].innerHTML.toUpperCase());
            if (products[i].innerHTML.toUpperCase().indexOf(searchValue) > -1)
              products[i].parentNode.style.display = '';
            else 
              products[i].parentNode.style.display = 'none';
          };
    };

CSS:

.product-container {
  display: flex;
  flex-direction: column;
  margin-bottom: 10px;
  background: grey;
}

.product-container span {
  font-size: 20px;
}

.product {
  display: block;
}

https://jsfiddle.net/gardelin/koc5eg6v/25/

Upvotes: 3

Related Questions