On every change of input, i need to remove all <li> elements where inner text don't match the input value. The problem is: it don't remove all lines that doesn't match at once.
My code:
<input name="tag-input" id="tag-input" type='text'>
<div id="list-pol">
<ul id="list-pol-select">
<li class="list-pol-item">Fish</li>
<li class="list-pol-item">Dog</li>
<li class="list-pol-item">Chameleon</li>
<li class="list-pol-item">Cat</li>
</ul>
</div>
<script type="text/javascript">
var input = document.getElementById('tag-input');
function updateList(){
if(document.getElementsByClassName("list-pol-item")[0]){
var list = document.getElementsByClassName("list-pol-item");
for (var i = 0; i < list.length; i++) {
var tag = list.item(i).innerText;
if(input.value !== tag.substring(0,input.value.length)){
list.item(i).remove();
}
}
}
}
input.addEventListener('input', updateList);
</script>
getElementsByClassName will give you a live collection, which is very confusing. If the ith element in the collection loses the class name, the collection will lose that element and shift down immediately. If that happens while you're trying to iterate over it - like here - you'll be in trouble.
const foos = document.getElementsByClassName('foo');
foos[0].remove();
console.log(foos.length);
console.log(foos[0]);
<div class="foo">1</div>
<div class="foo">2</div>
Turn it into a (non-live) array instead first - or use querySelectorAll, which returns a static NodeList.
var input = document.getElementById('tag-input');
function updateList() {
for (const item of document.querySelectorAll('.list-pol-item')) {
if (!item.textContent.startsWith(input.value)) {
item.remove();
}
}
}
input.addEventListener('input', updateList);
<input name="tag-input" id="tag-input" type='text'>
<div id="list-pol">
<ul id="list-pol-select">
<li class="list-pol-item">Fish</li>
<li class="list-pol-item">Dog</li>
<li class="list-pol-item">Chameleon</li>
<li class="list-pol-item">Cat</li>
</ul>
</div>
If you paste in "Fish", you'll see that Fish is the only item that remains.
But your current logic is weird - do you really want to .remove() the items that don't match? Unless someone pastes in text that matches exactly, everything will be removed. Did you want to toggle the items' display instead?
var input = document.getElementById('tag-input');
function updateList() {
for (const item of document.querySelectorAll('.list-pol-item')) {
item.classList.toggle('hidden', !item.textContent.startsWith(input.value));
}
}
input.addEventListener('input', updateList);
.hidden {
display: none;
}
<input name="tag-input" id="tag-input" type='text'>
<div id="list-pol">
<ul id="list-pol-select">
<li class="list-pol-item">Fish</li>
<li class="list-pol-item">Dog</li>
<li class="list-pol-item">Chameleon</li>
<li class="list-pol-item">Cat</li>
</ul>
</div>
You also might consider comparing the lower-cased input against the lower-cased list item, instead of requiring a case match for the elements to display.