The code below is for a simple search. Im trying to count the visible 'li' on the list and display the total in a div "totalClasses". and then when the user search for a class update the total with only the visible classes(li).
I have tried doing this ('li:visble') but is not working.
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>
The code below is for a simple search. Im trying to count the visible 'li' on the list and display the total in a div "totalClasses". and then when the user search for a class update the total with only the visible classes(li).
I have tried doing this ('li:visble') but is not working.
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/
Share Improve this question edited Jul 17, 2017 at 19:51 Tyler Roper 21.7k6 gold badges35 silver badges58 bronze badges asked Jul 17, 2017 at 19:47 Pedro Pedro 1,4502 gold badges16 silver badges44 bronze badges 1- 1 Why the jQuery tag? I don't see any. – j08691 Commented Jul 17, 2017 at 19:52
8 Answers
Reset to default 3you need to update the count everytime you call the event handler. you can do like 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";
}
'li:visible' is not a tag, you are adding a pseudo-selector and hoping for the best, which won't work.
You could go
ul.querySelectorAll('li:visible')
If you don't care about Firefox. If you do, I'd recommend jQuery.
ul.find('li:visible');
I would just store the count of show objects during the search function and update the relevant element at the end of the search function:
function search() {
var input, filter, ul, li, a, aa, count =0;
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 = '';
count++;
} else {
li[i].style.display = 'none';
}
}
document.getElementById('totalClasess').innerHTML = count + " Results";
}
Just update 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) + " 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 + " 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>
You are attempting to attach an event listener function before the element is loaded. Adding a line will do the trick
document.getElementById('myInput').onkeyup = search;
working code
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>
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 visibleLi = [];
var items = document.getElementById("myUl").getElementsByTagName("li");
for (var i = 0; i < items.length; i++) {
if (items[i].style.display != "none") {
visibleLi.push(items[i]);
}
}
document.getElementById('totalClasess').innerHTML = (visibleLi.length) + "
Results";
}
I have simplified your code:
https://jsfiddle.net/52bbqor9/1/
You can check for an item using the :not()
selector, and check to see if something does not exist, such as a class. You then would combine it with querySelectorAll
and get the length like this:
let itemCount = document.querySelectorAll('#myUl li:not(.hidden)').length;
As for the :visible
Pseudo-class Selector that is a jQuery thing and not a real JavaScript Pseudo-class. I created the class hidden
which you can see below.
I then removed your onkeyup
in your html and created it in the javascript below (I also changed it to input
instead). Otherwise the HTML hasn't changed.
<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>
Here is where I created a hidden
class that I add/remove based on the input text.
.hidden { display: none; }
Next we search for the item and test against a regular expression like so:
// Get the elements we want to work with
let input = document.querySelector('#myInput');
let list = document.querySelectorAll('#myUl li');
let results = document.querySelector('.results');
// Attach an eventlistener to the search box
input.addEventListener('input', e => {
// Create a regexp to test against each item
let search = new RegExp('^' + e.target.value, 'i');
// Loop 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');
}
}
// Get a count of li items without `.hidden`
results.innerText = 'Results ' + document.querySelectorAll('#myUl li:not(.hidden)').length;
});
The very last thing we do is get a count of all the items that don't have a .hidden
class attached to it and show it in the results
paragraph tag.