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

What could be causing the issue with my dynamic sitemap.xml file not functioning properly?

I have encountered an issue with creating a dynamic sitemap in my Next.js app. Despite following the instructions in the Next.js documentation and placing a sitemap.js file inside my app directory, I am seeing a 404 error when trying to access http://local ...

Receiving an empty string from Chrome FileReader when dealing with large files (300MB or more)

Objective: The task is to read a file from the user's file system as a base64 string in the browser The size of these files can be up to 1.5GB Challenge: A script that works flawlessly on Firefox, regardless of the file size On Chrome, the script p ...

Is there a way to display a loader when an item is selected from a dropdown menu? For example, while data is being fetched from the backend, can we

This is the HTML form division I have created: <div class="col-lg-2 "> <select name="limitCount" id="limitCount" ng-model="limitCount" class="form-control col-md-2 panel-refresh" ...

How to verify changes in session variable using PHP and AJAX

Hey there! I'm looking for a way to continually monitor changes in a session variable within PHP. Let's say the session variable "x" starts off with a value of "1" and then, after five seconds, it changes to "2". This session variable "x" is up ...

Displaying divs inline with overlapping child divs

As a beginner in CSS, I tackle the challenges of learning it every day. Despite feeling clumsy and not naturally adept at it, my determination is strong (although sometimes my brain feels like an old computer on the verge of overheating). My current goal i ...

Displaying a video in fullscreen on a webpage

Struggling to achieve the desired result, seeking advice from experts. Looking to create a classic example like this: http://codepen.io/anon/pen/rWwaRE But want it embedded within blocks of text and possibly triggered by scrolling over it similar to this ...

What is the process of converting the timing from my stopwatch to a standard time format?

I am currently working on a stopwatch project where I log the time into an array. However, when I try to use Math.min(array) or Math.max(array), it returns NaN (not a number). The time format for the stopwatch is like 00:00:15.91 which is not recognized as ...

Guide on updating data within a file at a specific position using JavaScript

I am faced with a challenge involving a file containing the following data, Test.txt, <template class="get" type="amp-mustache"> <div class="divcenter"> /////Need to append data at this point///// </div> </template> ...

The jQuery toggle menu seems to be malfunctioning

I am experiencing an issue with a menu on my website. The menu can be viewed here: http://jsfiddle.net/paTNz/2/ The problem occurs when I try to click directly under the word "English" - the menu suddenly closes. This is confusing to me because the event ...

AngularJS factory architecture for multiple functions

It's not the exact data I'm using in my project, but I'm simplifying it for demonstration purposes. In my AngularJS app, I have a factory like this: myApp.factory('inputinfo', function () { var self = { test: function (in) { ...

Adding npm packages to your Vue.js application

My Vue app is structured like this (auto created by vue init webpack myProject): index.html components/ -main.js -App.vue I am trying to include npm packages, such as https://github.com/ACollectionOfAtoms/atomic-bohr-model. Following the instructions, I ...

I am looking to showcase a series of icons linked together by connecting lines

I have successfully designed the layout and added icons, but I am facing difficulty in creating connecting lines between them. I attempted to utilize CSS borders and pseudo-elements, yet I cannot achieve the desired outcome. If anyone could offer a CSS-ba ...

Utilizing JQuery version 1.8.0 to seamlessly send files through forms using AJAX technology

Initially, I believed this issue was related to CakePHP development. However, after receiving an answer, I discovered that it had wider implications. Here is the revised question to reflect the more general nature of the solution. I am working on a form ...

Is it advisable to use type="text/plain" for JavaScript?

I recently came across instructions on how to implement a particular feature out of curiosity. I found it interesting but was puzzled when they mentioned that in order for it to function properly, certain steps needed to be followed: You must identify any ...

What is the best method to retrieve the value of a button that has been selected from a collection of buttons?

Within a functional component, there is an issue where the choose function keeps printing 'undefined'. I have utilized const [chosen, setchosen] = useState([]) within this code snippet. The full code has been correctly imported and the purpose of ...

Iframe not displaying Base64 encoded PDF in Chrome App

Currently, I am in the process of developing a Chrome App that essentially acts as a wrapper for the main app within a webview. The webview sends a Base64 encoded PDF as a message to the app, which then creates a hidden iframe and loads the PDF into the fr ...

What is the best practice for incorporating CSS and JavaScript files into a PHP template?

I've created a basic template for my PHP website, but I'm struggling to find the best way to include my CSS and JavaScript files. Take a look at my index.php file below: <?php include'core/template.php'; $temp=new Template(); $sett ...

Passing parameters to an Angular 2 component

When it comes to passing a string parameter to my component, I need the flexibility to adjust the parameters of services based on the passed value. Here's how I handle it: In my index.html, I simply call my component and pass the required parameter. ...

What is the best way to delete a table that I created through my programming?

I have utilized the following code to create a table: <html> <head> <title>Table Time</title> </head> <body> <table border="1px"> <tr> ...

Issue with Vue plugin syntax causing component not to load

I'm facing an issue with a Vue plugin that I have. The code for the plugin is as follows: import _Vue from "vue"; import particles from "./Particles.vue"; const VueParticles = (Vue: typeof _Vue, options: unknown) => { _Vue. ...