当文本框为空时隐藏元素

4

如果文本框为空,我无法隐藏myUL li元素。有什么建议吗?先谢谢了。

<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个回答

2
为了在输入为空时隐藏元素,您可以在检查用户是否输入值的if条件中包含filter值。
还要注意,通过使用不显眼的事件监听器、input事件和一些ES5方法,代码可以得到改进和简化。

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>


使用querySelector选择ID的特定原因是什么?并且使用两个querySelector / All来获取“#myInput li”的内容?这里有一个更简单的版本。链接 - mplungjan
2
非常好的观点。我盲目地将原始的两行代码组合在一起,没有考虑任何改进。已更新,谢谢。 - Rory McCrossan
2
你可能想在 display: nonedisplay: list-item 之间切换。不过我更喜欢使用 el.hidden - connexo
@connexo 两者之间切换隐藏和切换display:none和list-item的视觉区别是什么? - mplungjan
@mplungjan 没有视觉上的区别,我只是偏好使用现有的 API 而不是复制它。 - connexo
".hidden" 是自 IE10 以来已经存在的属性。 - mplungjan

2

这是我的版本

如果有ID和"#id li"的复合选择器,我更喜欢使用getElementById。

此外,我在HTMLCollection上使用展开运算符,因为旧版EDGE浏览器没有HTMLCollection上的forEach方法。

事实证明,IE11也支持hidden,因此这里有一个比我的第一个示例更短的版本。

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>

另外,当您有一个布尔值时,使用classList.toggle来隐藏内容也是非常好的。

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>


1
我更喜欢 el.hidden= !(filter && text.includes(filter)) - connexo
@connexo 我本来想说 classList.toggle 更受支持,但是 hidden 实际上也被 IE11 支持了 - 所以请查看更新。 - mplungjan
你的第一个代码示例仍然有 .hide,它并没有被使用。而且不需要使用扩展操作符,在支持扩展操作符的浏览器中也支持 NodeList 上的 forEach - connexo
@connexo 旧版 EDGE 支持 spread,但不支持在 Node 列表上使用 forEach。 - mplungjan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接