Using JavaScript to create a search bar: Can "no results found" only show after the user has completed typing their search query?

How can I ensure that the "no match" message only appears after the user has finished typing in their search query, rather than seeing it while they are still typing "De" and the list displays "Demi"?

usernameInput.addEventListener("keyup",function(){
    const usernameInput = document.getElementById("usernameInput")
    let userName = event.target.value.toLowerCase()
    let allNamesDOMCollection = document.getElementsByClassName("name")
    for(var count=0; count <  allNamesDOMCollection.length;count++) {
        const currentName = allNamesDOMCollection[count].textContent.toLowerCase()
        if(currentName.includes(userName)) {
            allNamesDOMCollection[count].style.display = "block";
            const nomatch = document.getElementById("nomatch");
            nomatch.style.display = "none"
        } else {
            allNamesDOMCollection[count].style.display = "none"; 
            const nomatch = document.getElementById("nomatch");
            nomatch.style.display = "block"
        }
      
    }
});
body {
  font-family: 'Rubik', sans-serif;
  width: 900px;
  margin:0 auto
}

.container {
  border: 3px solid;
  margin: 2rem 0rem
}

/* searchbar */

.searchbar {
  display:flex;
  background-color: orange;
  font-weight: 700;
  font-size: 2rem;
}

.searchbar {
  padding: 2rem;
}

#usernameInput {
  margin-left:1rem;
  width: 30%;
}


/* namelist */


.namelist {
  background-color: rgba(16,95,229,.8);
  padding: 1rem;
  
}

.liststar {
  list-style:none;
  margin:0;
  padding-left:0;
}

li {
  background-color: white;
  margin:0.5em;
  padding: 1rem;
  font-size:1.2rem;
  text-align:center;
}

#nomatch {
  display:none
}
<html>
  
  <body>
    <div class="container">
    <div class="searchbar">
      <label for="usernameInput">Search Users</label>
      <input id="usernameInput" type="text">
    
    </div>
   <div class="namelist">
     <ul class="liststar">
       <li class="name">Demi</li>
       <li class="name">Joe</li>
       <li class="name">Jojo</li>
       <li class="name">Lily</li>
       <li class="name">Tata</li>
       <li class="name">Momo</li>
       <li class="name">Dad</li>
       <li class="name">Sister</li>
       <li id="nomatch"> no match</li>
    </ul>
    </div>
    </div>
    
  </body>

Answer №1

The main issue you're facing is due to the fact that you are toggling the visibility of "no match" with each loop iteration (word in the list), instead of making that decision after completing the loop and checking all words. Simply move nomatch.style.display = ... outside the loop, ensuring it only gets set based on whether there was a match or not during the loop by using a tracking variable.

Moreover, your code includes some outdated syntax which can be optimized for clarity.

Take a look at the updated code below:

// Store DOM references efficiently
const nomatch = document.getElementById("nomatch");
const usernameInput = document.getElementById("usernameInput");

// Avoid using .getElementsByClassName() for better performance
let allNamesDOMCollection = document.querySelectorAll(".name");
       
usernameInput.addEventListener("keyup", function(){

  let searchValue = this.value.toLowerCase();
  let itemsFound = false; // Keep track of any matches
  
  // Use Array.forEach() to loop over node lists
  allNamesDOMCollection.forEach(function(currentName){
    if(currentName.textContent.toLowerCase().includes(searchValue)){
      currentName.style.display = "block";
      itemsFound = true;
    } else {
      currentName.style.display = "none"; 
    }
  });
  
  // Show/hide "no match" after checking all entries
  nomatch.style.display = itemsFound ? "none" : "block";
});
body {
  font-family: 'Rubik', sans-serif;
  width: 900px;
  margin:0 auto
}

.container {
  border: 3px solid;
  margin: 2rem 0rem
}

/* searchbar */

.searchbar {
  display:flex;
  background-color: orange;
  font-weight: 700;
  font-size: 2rem;
}

.searchbar {
  padding: 2rem;
}

#usernameInput {
  margin-left:1rem;
  width: 30%;
}


/* namelist */


.namelist {
  background-color: rgba(16,95,229,.8);
  padding: 1rem;
  
}

.liststar {
  list-style:none;
  margin:0;
  padding-left:0;
}

li {
  background-color: white;
  margin:0.5em;
  padding: 1rem;
  font-size:1.2rem;
  text-align:center;
}

#nomatch {
  display:none
}
<html>
  
  <body>
    <div class="container">
    <div class="searchbar">
      <label for="usernameInput">Search Users</label>
    <input id="usernameInput" type="text">
    
    </div>
   <div class="namelist">
     <ul class="liststar">
       <li class="name">Demi</li>
       <li class="name">Joe</li>
       <li class="name">Jojo</li>
       <li class="name">Lily</li>
       <li class="name">Tata</li>
       <li class="name">Momo</li>
       <li class="name">Dad</li>
       <li class="name">Sister</li>
       <li id="nomatch"> no match</li>
     </ul>
    </div>
    </div>
    
  </body>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Generate a random word using Typed.js

Can Typed.js generate a random word for output? $(function(){ $(".element").typed({ strings: ["Lorem", "Ipsum", "Dolor"], typeSpeed: 0 }); }); The output should be one of the following words. (Lorem / Ipsum / Dolor) ...

Having trouble executing node commands in the terminal

After launching the terminal on my Mac, I made sure to confirm that Node was installed by running the command: node -v v14.17.5 Next, when attempting to open a file I had created called index.html from Visual Studio Code, I encountered an error message in ...

How to manipulate wrapping behavior in flexbox

My flex container holds three divs, arranged in two rows: First row: One div with a fixed width Another div that should stretch to fill the remaining space Second row: Just one item However, the first div stretches to 100% width and pushes the seco ...

Utilizing reusable styled components with pseudo elements and advanced logic

How can I make the shared style more dynamic by changing the value of left or width based on a passed value or boolean logic across different components? I prefer not to pass it as a prop in the actual component like <bar left="20" />, but ...

Missing Bootstrap 3 Options Menu trip away

I created a table with 4 columns using the Bootstrap 3 grid system. Instead of utilizing the col-xs-* classes, which work well on mobile devices, I opted for the col-md-* classes. This decision was based on my preference to have larger and more visible ico ...

Ways to call a method in a subclass component from a functional parent component?

In my redux-store, I have objects with initial values that are updated in different places within the child component. As the parent, I created a stateless functional component like this: const Parent = () => { const store = useSelector(state => s ...

Ways to verify if an ajax function is currently occupied by a previous request

Is there a way to determine if an ajax function is occupied by a prior call? What measures can be taken to avoid invoking an ajax function while it is still processing a previous request with a readyState != 4 status? ...

Is there a way to hide the <v-otp-input> field in a Vue.js application?

For more information, please visit https://www.npmjs.com/package/@bachdgvn/vue-otp-input <script> export default { name: 'App', methods: { handleOnComplete(value) { console.log('OTP completed: ', value); } ...

The page's dimensions exceed the size of the device screen

I created this basic HTML content using React <!doctype html> <html><head><title data-react-helmet="true"></title><style type="text/css" data-styled-components="" data-styled-components-is-local="true"></style>< ...

The use of absolute positioning in conjunction with overflow:hidden

<div id="container" style="overflow:hidden; position:relative;"> <div id="content" style="position:absolute;"> </div> </div> Is it possible to display the content element which is larger than its parent container, while still k ...

Using AngularJS ui-router ui-sref results in the error message "Uncaught TypeError: Cannot read property '0' of undefined."

I am currently working on an angularJS component that utilizes ui-router with 2 straightforward route states. export default function Routes($stateProvider, $urlRouterProvider, $locationProvider) { $stateProvider .state('details', { ...

HTML: Align DIV contents next to each other without any overlap

Below are three boxes displayed. Boxes 1 and 3 appear fine, but in box 2 the text content is overlapping. The issue lies with the <div> having the class .vertical_center.grade_info which has a specific margin-left of 100px, causing the overlap. I ne ...

Pass a JavaScript array variable to a PHP script utilizing jQuery Ajax and receive a string output instead of an array

Whenever I attempt to transmit a JavaScript array to a PHP script via Ajax, the output of $_POST['file_paths'] when var_dumped shows up as a string instead of an array. My goal is to have the output in array format rather than in string format. C ...

What is the best way to implement sorting in a table using react virtualized?

I've been working on implementing sorting in my project using the table sorting demo available on Github. Here is the code I'm using: import React from 'react'; import PropTypes from 'prop-types'; import { Table, Column, Sor ...

Are you interested in creating dynamic tables/models with Sequelize?

Currently, I am exploring a theoretical question before diving into the implementation phase. The scenario is as follows: In my application, users have the ability to upload structured data such as Excel, CSV files, and more. Based on specific requirement ...

The mysterious behavior of CSS3 transforms on intricate rotations

When a div is viewed in perspective and has the transformations rotateY(-90deg) rotateX(-180deg), adding rotateZ(-90deg) to it results in a rotation of +270 degrees instead of -90 degrees. The new style of the div changes from transform: rotateY(-90deg) ...

Enable the jQuery UI Autocomplete feature with Google Places API to require selection and automatically clear the original input field when navigating with the

I am currently using a jquery ui autocomplete feature to fetch data from Google Places... The issue I am experiencing is that when the user navigates through the suggestions using the up and down arrows, the original input also appears at the end. I would ...

Detecting collisions between two squares in an HTML5 canvas

class Snake { constructor() { this.x = 400; this.y = 400; this.width = 25; this.height = 25; } draw() { ctx.fillRect(this.x, this.y, this.width, this.height); } } let snake = new Snake(); class ...

Dealing with Error TS2769 in Visual Studio Code when passing props to a custom component in Vue 2 with Typescript

I've encountered an issue with a Vue JS component that involves passing a custom prop. I am utilizing the Vue Options API without utilizing the class component syntax. Whenever I pass ANY prop to my custom component the-header, I receive an error sta ...

Preventing the use of scripting tags in text boxes

I'm currently trying to integrate the post feature on my website using codeigniter (PHP). However, I've run into an issue where when I input and submit the following code: <script> alert("aaaa"); </script> The JavaScript starts exec ...