Reputation: 23
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
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