Home > other >  My search bar appear but not working, whenever I type in the keyword, the page will still be the sam
My search bar appear but not working, whenever I type in the keyword, the page will still be the sam

Time:01-07

I've been trying to make a search bar for my e-commerce website for the user to find their favorite product.

I had to use javascript to make the search bar workable but it still not working, the search bar appears but it can't be used, whenever you type in something, the page will still be the same without changing and sorting for the keyword.

My Javascript:

const search = () => {
    const searchbox = document.getElementById("search-item").value.toUpperCase();
    const storeitems = document.getElementById("game-list")
    const product = document.querySelectorAll("pro")
    const pname = storeitems.getElementsByTagName("h5")

    for (var i = 0; i < pname.length; i  ) {
        let match = product[i].getElementsByTagName('h5')[0];

        if (match) {
            let textvalue = match.textContent || match.innerHTML

            if (textvalue.toUpperCase().indexOf(searchbox) > -1) {
                product[i].style.display = "";
            } else {
                product[i].style.display = "none";
            }
        }
    }
}
 <form>
        <i ></i>
        <input type="text" name="" id="search-item" placeholder="Search here" onkeyup="search()">
 </form>

    <section id="product1" >
        <div  id="game-list">
            <div  onclick="window.location.href='sproduct.html'">
                <img src="img/products/f1.jpg" alt="">
                <div >
                    <span>Developer : CD PROJEKT RED</span>
                    <h5>CYBERPUNK</h5>
                    <div >
                        <i ></i>
                        <i ></i>
                        <i ></i>
                        <i ></i>
                        <i ></i>
                    </div>
                    <h4>$85</h4>
                </div>
                <a href="#"><i ></i></a>
            </div>

CodePudding user response:

The issue is in the line

const product = document.querySelectorAll("pro")

That should be const product = document.querySelectorAll(".pro") instead.

querySelectorAll receives an argument that must be a valid CSS selector string.

In your example i think you mean to target the element <div onclick="window.location.href='sproduct.html'"> which has a class "pro". The valid selector for that is .pro as opposed to just pro without the dot at the beginning.

https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll

Try this:

const search = () => {
    const searchbox = document.getElementById("search-item").value.toUpperCase();
    const storeitems = document.getElementById("game-list")
    
    const product = document.querySelectorAll(".pro")
    const pname = storeitems.getElementsByTagName("h5")

    for (var i = 0; i < pname.length; i  ) {
        let match = product[i].getElementsByTagName('h5')[0];

        if (match) {
            let textvalue = match.textContent || match.innerHTML

            if (textvalue.toUpperCase().indexOf(searchbox) > -1) {
                product[i].style.display = "";
            } else {
                product[i].style.display = "none";
            }
        }
    }
}
<div><form>
        <i ></i>
        <input type="text" name="" id="search-item" placeholder="Search here" onkeyup="search()">
 </form>

    <section id="product1" >
        <div  id="game-list">
            <div  onclick="window.location.href='sproduct.html'">
                <img src="img/products/f1.jpg" alt="">
                <div >
                    <span>Developer : CD PROJEKT RED</span>
                    <h5>CYBERPUNK</h5>
                    <div >
                        <i ></i>
                        <i ></i>
                        <i ></i>
                        <i ></i>
                        <i ></i>
                    </div>
                    <h4>$85</h4>
                </div>
                <a href="#"><i ></i></a>
            </div>
            </div>
            </section>
</div>

CodePudding user response:

I know this is totally overkill from the question you asked, but I made a CodePen just to give you a possibly better way of doing what you're trying to do. At the very least, it will probably help you understand JavaScript a little bit more. CodePen

In case you just want to see the code:

const shoppingItems = [
  {
    name: 'Laptop',
    description: 'Dell Inspiron with Intel Core i5 processor, 8GB RAM, and 256GB SSD',
    price: 499.99,
    rating: 4,
    keywords: ['computer', 'Intel Core i5', 'Dell']
  },
  {
    name: 'Smartphone',
    description: 'Samsung Galaxy S20 with 6.2-inch display, triple rear camera, and 5G capability',
    price: 799.99,
    rating: 5,
    keywords: ['phone', 'Samsung', 'Galaxy S20', '5G']
  },
  {
    name: 'TV',
    description: 'LG OLED 4K TV with Dolby Vision and HDR10 support',
    price: 999.99,
    rating: 5,
    keywords: ['television', 'LG', 'OLED', '4K']
  },
  {
    name: 'Headphones',
    description: 'Beats Solo3 wireless headphones with 40 hours of battery life and noise cancellation',
    price: 199.99,
    rating: 4,
    keywords: ['headphones', 'Beats', 'wireless', 'noise cancellation']
  },
  {
    name: 'Fitness Tracker',
    description: 'Fitbit Charge 4 with GPS, heart rate monitor, and built-in Alexa',
    price: 149.99,
    rating: 3,
    keywords: ['fitness tracker', 'Fitbit', 'GPS', 'heart rate monitor']
  }
]

// Select the template element and the container for search results
const itemTemplate = document.querySelector('[data-item="template"]'),
      resultsContainer = document.querySelector('#search-results'),
      searchInput = document.querySelector('#search-input')

// Declare variables to store the search buffer timeout and the closest above and below items
let searchBuffer,
    closestAbove,
    closestBelow

// Add an event listener to the search input element that listens for keyup events
searchInput.addEventListener('keyup', (e) => {
  
  // Clear the search buffer timeout
  clearTimeout(searchBuffer)
  
  // Set a new timeout for the search buffer
  searchBuffer = setTimeout(() => {
    
    // Clear the search results container
    resultsContainer.innerHTML = ''
    
    // Get the search value from the search input element
    const searchValue = searchInput.value
    
    // Reset the closest above and closest below items
    closestAbove = { price: Infinity }
    closestBelow = { price: -Infinity }
    
    // Loop through each shopping item
    shoppingItems.forEach(shoppingItem => {
  
      // Set the display flag to false
      let display = false
      
      // Check if the search value is in the name or description of the item
      if (
        shoppingItem.name.toLowerCase().includes(searchValue.toLowerCase())
        ||
        shoppingItem.description.toLowerCase().includes(searchValue.toLowerCase())
      ) display = true
      
      // If the display is still false, check if the search value is in any of the item's keywords
      if (!display) {
        shoppingItem.keywords.forEach(keyword => {
          if (keyword.toLowerCase().includes(searchValue.toLowerCase())) display = true
        })
      }
      
      // If the display is still false, check if the search value is a price
      if (!display) {
        
        // If the item's price is greater than or equal to the search value and less than the current closest above item, set the closest above item to this item
        if (
          shoppingItem.price >= Number(searchValue)
          &&
          shoppingItem.price < closestAbove.price
        ) closestAbove = shoppingItem
        
        // If the item's price is less than or equal to the search value and greater than the current closest below item, set the closest below item to this item
        if (
          shoppingItem.price <= Number(searchValue)
          &&
          shoppingItem.price > closestBelow.price
        ) closestBelow = shoppingItem

      }
      
      // If the search value is an empty string, don't display the item
      if (searchValue === '') display = false

      // If the display flag is true, display the item
      if (display) displayItem(shoppingItem)

    })
    
    // If the closest above item has a price less than Infinity or the closest below item has a price greater than -Infinity, display it
    if (
      closestAbove.price < Infinity
      ||
      closestBelow.price > -Infinity
    ) displayItem(closestAbove)

  }, 500)
  
})

/**
 * Displays a shopping item in the search results container
 * @param {Object} item - The shopping item to display
 * @param {string} item.name - The name of the item
 * @param {string} item.description - The description of the item
 * @param {number} item.price - The price of the item
 * @param {number} item.rating - The rating of the item (out of 5)
 */
function displayItem(item) {
  
  // Destructure the item object and create a few other variables
  const { name, description, price, rating } = item,
        starsRating = [],
        randomHue = Math.floor(Math.random() * 360),
        randomHsl = `hsl(${randomHue} 75% 40%)`
  
  // Create an array of filled or empty starts for the rating
  for (let i = 0; i < 5; i  ) {
    rating <= i
    ?
    starsRating.push('☆')
    :
    starsRating.push('★')
  }
  
  // Clone the item template element and select some of its child elements
  const searchedItem = itemTemplate.content.cloneNode(true),
        nameField = searchedItem.querySelector('[data-item="name"]'),
        priceField = searchedItem.querySelector('[data-item="price"]'),
        ratingField = searchedItem.querySelector('[data-item="rating"]'),
        descriptionField = searchedItem.querySelector('[data-item="description"]'),
        hr = searchedItem.querySelector('hr')
  
  // Set the box shadow of the searchItem element to a random hue
  descriptionField.parentNode.style.boxShadow = `0 0.25rem 2rem hsl(0 0% 0% / 0.15), 0 0 5rem hsl(${randomHue} 100% 50% / 0.15)`
  
  // Set the inner text and color of the name field to the item's name and a random hue
  nameField.innerText = name
  nameField.style.color = randomHsl
  
  // Set the inner text of the price field to the item's price
  priceField.innerText = `$${price}`
  
  // Set the inner text and color of the rating field to the rating array and a random hue, and set the text shadow of the field to a random hue
  ratingField.innerText = starsRating.join('')
  ratingField.style.color = randomHsl
  ratingField.style.textShadow = `0 0 0.25rem hsl(${randomHue} 100% 50% / 0.4)`
  
  // Set the inner text of the description field to the item's description
  descriptionField.innerText = description
  
  // Set the border color of the hr element to a random hue
  hr.style.borderColor = randomHsl
  
  // Append the cloned and modified item template element to the search results container
  resultsContainer.appendChild(searchedItem)
}
*,
html,
body {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  position: relative;
  font-family: sans-serif;
}
.container {
  padding: 2rem;
  background-color: lightgray;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
input {
  padding: 0.5rem;
  border-radius: 0.5rem;
  border: none;
  font-size: 1rem;
}
input::placeholder {
  color: gray;
}
ul {
  list-style-type: none;
  display: grid;
  grid-auto-flow: row;
  gap: 1rem;
}
li {
  background-color: white;
  padding: 1rem;
  display: grid;
  grid-auto-flow: row;
  gap: 1.25rem;
  border-radius: 1rem;
}
.item-top-container {
  display: grid;
  grid-auto-flow: row;
  gap: 0.25rem;
}
.rating-price-container {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
[data-item="price"],
[data-item="rating"] {
  font-size: 0.9rem;
}
hr {
  border-width: 1px;
  border-style: solid;
  border-radius: 1rem;
}
<div class='container'>
  
  <input id='search-input' type="text" placeholder="Search our store" />
  
  <h2>Results</h2>
  <ul id="search-results"></ul>
  
  <template data-item="template">
    
    <li data-item="container">
      
      <div class='item-top-container'>
        
        <h3 data-item="name"></h3>
      
        <div class='rating-price-container'>

          <p data-item="price"></p>

          <p data-item="rating"></p>

        </div>

      </div>
      
      <hr>
      
      <p data-item="description"></p>
      
    </li>
    
  </template>
  
</div>

  • Related