Hiding elements when a textbox empty

Viewed 138

I am unable to hide the myUL li elements if the textbox is empty. Any ideas? Thanks in advance.

<input type="text" id="myInput" onKeyUp="myFunction()" placeholder="Just begin typing.." title="Detail Index">
<ul id="myUL">
  <li><a href="/year/2000.html" target="_blank">2000</a></li>
  <li><a href="/year/2001.html" target="_blank">2001</a></li>
  <li><a href="/year/2002.html" target="_blank">2002</a></li>
</ul>
<script>
  function myFunction() {
    var input, filter, ul, li, a, i, txtValue;
    input = document.getElementById("myInput");
    filter = input.value.toUpperCase();
    ul = document.getElementById("myUL");
    li = ul.getElementsByTagName("li");
    for (i = 0; i < li.length; i++) {
      a = li[i].getElementsByTagName("a")[0];
      txtValue = a.textContent || a.innerText;
      if (txtValue.toUpperCase().indexOf(filter) > -1) {
        li[i].style.display = "";
      } else {
        li[i].style.display = "none";
      }
    }
  }
</script>

2 Answers

To have the elements hidden when the input is empty you can include the filter values in the if condition which checks that the user has entered a value.

Also note that the code can be improved and simplified by using unobtrusive event listeners, the input event and some ES5 methods:

document.querySelector('#myInput').addEventListener('input', () => {
  let filter = document.querySelector('#myInput').value.toUpperCase();
  document.querySelectorAll('#myUL li').forEach(el => {
    let a = el.querySelector('a'); // gets the first only
    el.style.display = filter && (a.textContent || a.innerText).toUpperCase().indexOf(filter) != -1 ? 'list-item' : 'none';
  });
});
li { display: none; }
<input type="text" id="myInput" placeholder="Just begin typing.." title="Detail Index">
<ul id="myUL">
  <li><a href="/year/2000.html" target="_blank">2000</a></li>
  <li><a href="/year/2001.html" target="_blank">2001</a></li>
  <li><a href="/year/2002.html" target="_blank">2002</a></li>
</ul>

Here is my version

I prefer using getElementById when there is an ID and a compound selector with "#id li"

Also I use the spread operator on the HTMLCollection since older EDGE browsers does not have forEach on an HTMLCollection

It turns out that hidden is supported by IE11 too so here is an even shorter version than my first example at the end

document.getElementById('myInput').addEventListener('input', e => {
  let input = e.target;
  let filter = input.value.toUpperCase();
  let li = document.querySelectorAll('#myUL li');

  [...li].forEach(el => {
    const a = el.querySelector('a'); // gets the first only
    const text = a.textContent.toUpperCase();
    const show = filter && text.includes(filter);
    el.hidden = !show;
  });
});
<input type="text" id="myInput" placeholder="Just begin typing.." title="Detail Index" autocomplete="off">
<ul id="myUL">
  <li hidden><a href="/year/2000.html" target="_blank">2000</a></li>
  <li hidden><a href="/year/2001.html" target="_blank">2001</a></li>
  <li hidden><a href="/year/2002.html" target="_blank">2002</a></li>
</ul>

Alternatively classList.toggle is great to hide stuff when you have a boolean

document.getElementById('myInput').addEventListener('input', e => {
  let input = e.target;
  let filter = input.value.toUpperCase();
  let li = document.querySelectorAll('#myUL li');

  [...li].forEach(el => {
    const a = el.querySelector('a'); // gets the first only
    const text = a.textContent.toUpperCase();
    const show = filter && text.includes(filter);
    el.classList.toggle("hide",!show); 
  });
});
.hide { display: none; }
<input type="text" id="myInput" placeholder="Just begin typing.." title="Detail Index" autocomplete="off">
<ul id="myUL">
  <li class="hide"><a href="/year/2000.html" target="_blank">2000</a></li>
  <li class="hide"><a href="/year/2001.html" target="_blank">2001</a></li>
  <li class="hide"><a href="/year/2002.html" target="_blank">2002</a></li>
</ul>

Related