Counting the number of visible 'li' elements on a search list: A guide

In the following code snippet, I am attempting to create a simple search functionality. The goal is to count the visible 'li' elements in a list and display the total in a div called "totalClasses." Additionally, when the user searches for a specific class, only the visible classes should be included in the total count.

I have attempted to achieve this using ('li:visble'), but it seems to not be working as expected.

ul = document.getElementById('myUl');
li = ul.getElementsByTagName('li');
aa = ul.getElementsByTagName('li:visible');
document.getElementById('totalClasess').innerHTML = (aa.length) + " Results";

function search() {
  var input, filter, ul, li, a, aa;
  input = document.getElementById('myInput');
  filter = input.value.toUpperCase();
  ul = document.getElementById('myUl');
  li = ul.getElementsByTagName('li');

  for (var i = 0; i < li.length; i++) {
    a = li[i].getElementsByTagName('a')[0];
    if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
      li[i].style.display = '';
    } else {
      li[i].style.display = 'none';
    }
  }
}
<input type="text" id="myInput" onkeyup="search()" placeholder="Search for a class..." title="Type something">
<p class="results">Results</p>
<p id="totalClasess"></p>
<ul id="myUl">
  <li><a href="#" class="header">Section 1</a></li>
  <li><a href="#">Class 1 </a></li>
  <li><a href="#">Class 2</a></li>
  <li><a href="#">Class 3</a></li>
</ul>

DEMO: https://jsfiddle.net/52bbqor9/

Answer №1

To ensure the accuracy of the count, make sure to update it each time the event handler is called. Here's an example of how you can achieve this:

function search()
{
   var input, filter, ul, li, a, aa;
   input  = document.getElementById('myInput');
   filter = input.value.toUpperCase();
   ul     = document.getElementById('myUl');
   li     = ul.getElementsByTagName('li'); 
   var liCount = 0;
   for(var i=0; i<li.length; i++){
        a = li[i].getElementsByTagName('a')[0];
        if(a.innerHTML.toUpperCase().indexOf(filter) > -1){ 
            li[i].style.display = '';
            liCount++;
        } else {
            li[i].style.display = 'none';
        }
    }
    document.getElementById('totalClasess').innerHTML = liCount + " Results";
}

Answer №2

The pseudo-selector 'li:visible' is not a valid tag, so simply adding it and hoping for the best won't yield the desired results.

One alternative approach could be:

ul.querySelectorAll('li:visible')

However, if cross-browser compatibility, especially with Firefox, is important, using jQuery might be a better choice.

ul.find('li:visible');

Answer №3

To enhance the efficiency of the search function, I recommend storing the count of displayed items while iterating through them and updating the total at the end of the search process:

function improveSearch() {
  let input, filter, ul, li, a, count = 0;
  input = document.getElementById('searchInput');
  filter = input.value.toUpperCase();
  ul = document.getElementById('resultsList');
  li = ul.getElementsByTagName('li');

  for (let i = 0; i < li.length; i++) {
    a = li[i].getElementsByTagName('a')[0];
    if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
      li[i].style.display = '';
      count++;
    } else {
      li[i].style.display = 'none';
    }
  }

  document.getElementById('totalResults').innerHTML = count + " Items Found";
}

Answer №4

Keep track of the count while searching

var ip = document.getElementById('myInput');
var ul = document.getElementById('myUl');
var li = ul.getElementsByTagName('li');

document.getElementById('totalClasess').innerHTML = (li.length) + " Matching Results";

ip.addEventListener('input', function() {
  var val = this.value.toUpperCase(), idx = 0;

  for (var i = 0; i < li.length; i++) {
    var txt = li[i].textContent.toUpperCase();

    if (txt.indexOf(val) != -1) {
      li[i].style.display = 'block';
      idx++;
    } else {
      li[i].style.display = 'none';
    }

    document.getElementById('totalClasess').innerHTML = idx + " Matching Results";
  }
});
<input type="text" id="myInput" placeholder="Search for a class..." title="Type something">
<p class="results">Results</p>
<p id="totalClasess"></p>
<ul id="myUl">
  <li><a href="#" class="header">Section 1</a></li>
  <li><a href="#">Class 1 </a></li>
  <li><a href="#">Class 2</a></li>
  <li><a href="#">Class 3</a></li>
</ul>

Answer №5

Trying to register an event listener function before the element has finished loading? Just adding a single line can solve the issue.

document.getElementById('inputField').onkeyup = searchInput;

Check out the code in action

Answer №6

ul = document.getElementById('myUl');
li = ul.getElementsByTagName('li');

divs = document.querySelectorAll('#myUl > li');
var divsArray = [].slice.call(divs);
var aa = divsArray.filter(function(el) {
    return getComputedStyle(el).display !== "none"
});


document.getElementById('totalClasess').innerHTML = (aa.length) + " Results";

function search() {
  var input, filter, ul, li, a, aa;
  input = document.getElementById('myInput');
  filter = input.value.toUpperCase();
  ul = document.getElementById('myUl');
  li = ul.getElementsByTagName('li');

  for (var i = 0; i < li.length; i++) {
    a = li[i].getElementsByTagName('a')[0];
    if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
      li[i].style.display = '';
    } else {
      li[i].style.display = 'none';
    }
  };
  var divsArray = [].slice.call(divs);
    aa = divsArray.filter(function(el) {
    return getComputedStyle(el).display !== "none"
});
document.getElementById('totalClasess').innerHTML = (aa.length) + " Results";
}
<input type="text" id="myInput" onkeyup="search()" placeholder="Search for a class..." title="Type something">
<p class="results">Results</p>
<p id="totalClasess"></p>
<ul id="myUl">
  <li><a href="#" class="header">Section 1</a></li>
  <li><a href="#">Class 1 </a></li>
  <li><a href="#">Class 2</a></li>
  <li><a href="#">Class 3</a></li>
</ul>

Answer №7

function performSearch() {
var input, filter, ul, li, a, aa;
input = document.getElementById('searchInput');
filter = input.value.toUpperCase();
ul = document.getElementById('resultsList');
li = ul.getElementsByTagName('li');

for (var i = 0; i < li.length; i++) {
    a = li[i].getElementsByTagName('a')[0];
    if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {

        li[i].style.display = '';
    } else {
        li[i].style.display = 'none';
    }
}

var visibleItems = [];
var items = document.getElementById("resultsList").getElementsByTagName("li");
for (var i = 0; i < items.length; i++) {

    if (items[i].style.display != "none") {
        visibleItems.push(items[i]);
    }
}
 document.getElementById('searchResults').innerHTML = (visibleItems.length) + " Results";
}

Answer №8

I have simplified the code for you:

https://jsfiddle.net/52bbqor9/1/

To check for an item using the :not() selector and verify if something does not exist, like a class, combine it with querySelectorAll to get the length as shown below:

let itemCount = document.querySelectorAll('#myUl li:not(.hidden)').length;

The :visible Pseudo-class Selector belongs to jQuery and not JavaScript. I created the hidden class which is utilized in the code.

The onkeyup in the HTML has been removed and restructured in the Javascript section (changed to input). The HTML remains unchanged.

<input type="text" id="myInput" placeholder="Search for a class..." title="Type something">
<p class="results">Results</p>
<p id="totalClasess"></p>
<ul id="myUl">
  <li><a href="#" class="header">Section 1</a></li>
  <li><a href="#">Class 1 </a></li>
  <li><a href="#">Class 2</a></li>
  <li><a href="#">Class 3</a></li>
</ul>

The creation of the hidden class that is added/removed based on the input text can be seen below.

.hidden { display: none; }

We then proceed to search for the item and test against a regular expression in the following manner:

// Fetch the elements we are dealing with
let input = document.querySelector('#myInput');
let list = document.querySelectorAll('#myUl li');
let results = document.querySelector('.results');

// Add an event listener to the search box
input.addEventListener('input', e => {
  // Create a regexp to evaluate each item
  let search = new RegExp('^' + e.target.value, 'i');
  // Iterate through the list of li items
  for (let item of list) {
    // Test the current item
    if (search.test(item.innerText.trim())) {
      // Remove the hidden class if it matches
      item.classList.remove('hidden');
    } else {
      // Add the hidden class if it doesn't match
      item.classList.add('hidden');
    }
  }
  // Obtain a count of li items without `.hidden`
  results.innerText = 'Results ' + document.querySelectorAll('#myUl li:not(.hidden)').length;
});

Finally, we calculate the number of items without the .hidden class attached to them and display it in the results paragraph tag.

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

Having trouble connecting to my MongoDB container using Node.js

I am facing an issue while trying to connect my local mongoDB docker, named "some-mongo", to my NodeJS backend server running on the same computer. The problem arises when attempting to establish the connection using the "mongoose" module. To launch my mo ...

Is there a way to automatically transfer the ID from the first table to the id_position field in the second table upon clicking submit?

I'm dealing with two tables and I need to figure out how to add the id of the first table to the position_id field of the second table upon submitting. My request is done through ajax. The fields for the second table are dynamic, meaning you can keep ...

When trying to access Ajax fetched data within a VueJS `router-view`, the `$root` object returns undefined only when navigating directly to

As I familiarize myself with vuejs, I decided to challenge myself by creating a webpage similar to an eshop for practice purposes. My approach involves fetching all the necessary data in a single api call to ensure easy access from all my router-views for ...

When will the javascript file fire if it has this implementation?

Can someone help me make sense of this jquery snippet? (function( window, undefined ) { //All the JQuery code is included here ... })(window); I'm curious, if a .js file is loaded in a page using the <script> tag, at what point does it ...

A guide on how to automatically preselect a RadioGroup option in Material-UI

When a user selects an option from the MCQ Select using RadioGroup in my code and submits it, they should be able to return later and see the option they selected highlighted, similar to how Google Forms allows users to review their selections. Below is t ...

AngularJS $http.get('') is throwing an error because some parameters are missing

I am currently working on an application that utilizes OAuth for authentication, but I am facing some issues with passing the URL parameters correctly. Despite trying various methods, my API keeps returning an error stating that the username and password a ...

Steps for accessing registration form data once the signup button has been clicked

Hello everyone! I have a code that includes login and registration forms as tabs. When we click on either one, it goes to the respective form. Now, I want to make a change by removing the Register tab and adding it as a signup button next to the login butt ...

Eliminate placeholder text when the tab key is pressed

I'm currently facing an issue with a textarea that has a placeholder and the Tab key functionality in Internet Explorer. I've included placeholder.js to make it work, but when I repeatedly press the tab key and focus on the textarea, the placehol ...

Larger icon graphics

Is it possible to increase the size of Glyphicons in Twitter Bootstrap 3.0 without using the btn-lg class? I found this code that makes glyphicons big: <button type="button" class="btn btn-default btn-lg"> <span class="glyphicon glyphicon-th- ...

Tips for adjusting the width of the scrollbar track (the line beneath the scrollbar)

How can I style a scrollbar to match this specific design? https://i.stack.imgur.com/KTUbL.png The desired design specifies that the width of -webkit-scrollbar-thumb should be 5px and the width of -webkit-scrollbar-track should be 2px. However, it is pro ...

Issue with Bootstrap4 card alignment on Chrome browser

Hey there! I could use some assistance with an issue I'm facing in Bootstrap4 cards while using Chrome. The strange thing is that everything seems to be working fine on IE11, but not on Chrome. Take a look at the comparison images below: IE11 layout ...

Most effective strategy for handling PHP processing delays

As a newcomer to web programming, I appreciate your patience with me. I have developed a web page that submits form data to a PHP exec() function. This function retrieves data from a website, processes it in different ways, and saves it on my server. Whil ...

Interacting with jQuery UI Droppable by setting acceptance criteria before submitting a form

My goal is to create a draggable item that can be dropped onto a specific zone. The challenge I'm facing is in displaying a form for inputting information and storing it in a database. If the input is successfully stored, the drop action will be succe ...

Transmitting form information to a nested page within a div container

This is my fourth attempt to seek an answer to this question, as I've faced downvotes in previous attempts. So here we go again. I am trying to send data from a hidden input within a form using ajax. The value of the hidden input is generated by a php ...

Is there any HTML code that is able to implement a currency format identical to the one we've customized in Google Sheets/Google Apps Script

I am currently working with a Google Sheet table that consists of 2 columns. The second column contains charges which can vary based on user input through a Google Form and are summed up using GAS. To view an example, click here. The data from this Googl ...

Logging to the console using an If/Else statement, with the Else block containing code that

I'm encountering a peculiar issue with my If statement. I'm modifying the state (true/false) of an object based on onMouseEnter and onMouseLeave. I can execute the code when it's true, but if I include any code in the else statement, it ma ...

Manipulate inherited CSS styles from an external source

Currently, I am working on creating a pagination using the NG-Bootstrap pagination component. However, I encountered an issue where I need to modify or specifically remove some CSS properties that are applied by default in the NG-Bootstrap library. Is ther ...

How to align content in the center horizontally and vertically using HTML and CSS

I'm having trouble centering my content both vertically and horizontally on the page. Can anyone provide assistance? Thank you. <style type = "text/css"> #loginMenu { border:5px solid green; padding:10px 10px 10px 10px; background-color:#FF9; ...

``Is it possible to iterate through a collection of objects using a loop?

I am facing an issue with updating a global array that contains objects, where each object includes another array. My goal is to update the main array with values from the arrays within the objects following a specific logic! generalArray = [{name:String, ...

Uncertainties surrounding the use of JSON data versus a JavaScript object

As a newcomer to programming, I have ventured into Stack Overflow and W3schools to enhance my skills. Recently, I created a small project for educational purposes. One dilemma is bothering me - is the JSON file I generated actually in proper JSON format o ...