user15882535
user15882535

Reputation:

How to design a search box for a website?

I got a customize li filter for a website but I need to hide the all li in the initial stage. I need to hide all li in the page and show only the searching li. But the problem is when I try to hide the li, it also block all the li during result.

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";
        }
    }
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search...">

<ul id="myUL">
  <li><a href="#">tree</a></li>
  <li><a href="#">bike</a></li>
  <li><a href="#">sea</a></li>
  <li><a href="#">mobile</a></li>
</ul>

Upvotes: 2

Views: 151

Answers (4)

RDU
RDU

Reputation: 1071

I've quickly refactored you code so it support multiple values and preserves the list with links in case you wanted that.

This also only creates the list items that match the search term.

I don't know if this is better for performance but it's easier to add elements to the array rather than create html elements to hold the values.

    function myFunction() {
        let ul = document.querySelector('#myUL')
        ul.innerHTML = '';
        
        let inputVal = document.querySelector("#myInput").value;
        if(inputVal.length == 0){
            return;
        }

        
        let possibleValues = ['tree', 'bike', 'sea', 'mobile'];
        
        let resSpan = document.querySelector('#res');
        let resVal = [];
        
        
        possibleValues.forEach(str => {
            if(str.includes(inputVal)){
                resVal.push(str)
            }
        })
        
        if(resVal.length > 0){
            resVal.forEach(v => {
                let newLi = document.createElement('li');
                let newAnc = document.createElement('a');
                
                newAnc.innerText = v;
                newLi.appendChild(newAnc);
                ul.appendChild(newLi);
            })
        } 

        
    }
    <input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search...">
    <ul id="myUL"></ul>

Upvotes: 1

me.nkr
me.nkr

Reputation: 108

const input = document.getElementById("myInput");
const ul = document.getElementById("myUL");
const li = ul.getElementsByTagName("li");
for (i of li) i.style.display = "none" ;

function myFunction() {
  let filter, a, i, txtValue;
  filter = input.value.toUpperCase();
  if (filter) {
    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 = "block";
      } else {
        li[i].style.display = "none";
      }
    }
  }else for (i of li) i.style.display = "none" ;
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search...">

<ul id="myUL">
  <li><a href="#">tree</a></li>
  <li><a href="#">bike</a></li>
  <li><a href="#">sea</a></li>
  <li><a href="#">mobile</a></li>
</ul>

Upvotes: 0

N8Javascript
N8Javascript

Reputation: 150

Alright, below is a working version of your code. I know this question has already been answered, but this version supports multiple lis coming up as search results:

(Made 2 changes - the lis start of hidden, and then re-hide when the search bar is empty)

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 && filter.length > 0) {
            li[i].style.display = "";
        } else {
            li[i].style.display = "none";
        }
    }
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search...">

<ul id="myUL">
  <li style="display:none;"><a href="#">tree</a></li>
  <li style="display:none;"><a href="#">bike</a></li>
  <li style="display:none;"><a href="#">sea</a></li>
  <li style="display:none;"><a  href="#">mobile</a></li>
</ul>

Upvotes: 0

DecPK
DecPK

Reputation: 25408

You can hide all the li elements if the input is an empty string i.e. "" and run the function when the user types in input and the first time when the JS loads.

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");

  if (input.value === "") {
    [...li].forEach((liElement) => {
      liElement.style.display = "none";
    });
  } else {
    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";
      }
    }
  }
}

myFunction();
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search...">

<ul id="myUL">
  <li><a href="#">tree</a></li>
  <li><a href="#">bike</a></li>
  <li><a href="#">sea</a></li>
  <li><a href="#">mobile</a></li>
</ul>

Upvotes: 1

Related Questions