Real-time search using basic JavaScript

real-time search using basic javascript

Introduction

We have all seen a lot of websites which have real-time search filtering. This looks really good and provides a convenient user experience. If you are still wondering what real-time search is, it is a way of displaying the filtered result as the user is typing. This is much better than waiting for the user to finish typing the whole search query and then press a button. Real-time search saves time because the user need not type the whole query as there is a high chance that he/she will see the intended result before completing the query.

The concept behind filtering

The concept is quite simple. To conduct a search filter, we need something to search from. A list of sorts which has a collection of strings from which the user will search. It’s quite understood that we need to use an array for this in JavaScript.

So, now we have an array of strings to search from. Now, we need to make a function that can fetch all the relevant strings from the array based on the user’s search query. And this function needs to be called for every letter the user types. Based on the result of this function, we need to change the view and display the result on the screen. That’s it. That is the concept behind real-time search.

Now let’s get coding

  1. Let’s make a simple HTML page with a search box and an unordered list with a few dummy items. Create a new directory and in that create an “index.html” file. In that file, put some basic HTML code with an ‘input’ tag and an ‘ol’ tag with a few dummy ‘li’ tags in
    <html>
    <head>
        <title>Realtime search demo</title>
    </head>
    <body>
        <input type="search" placeholder="search..." />
        <ul id="result-list">
            <li>sample result</li>
            <li>sample result</li>
            <li>sample result</li>
        </ul>
    </body>
    </html>
    

    Simple HTML code

  2. In this step, let’s create the array we were talking about. In the same directory create a file called “main.js”. In that file copy-paste the below array.
    let arr = ["anagrams-of-string-(with-duplicates)", "array-concatenation", "array-difference", "array-includes", "array-intersection", "array-remove", "array-sample", "array-union", "array-without", "array-zip", "average-of-array-of-numbers", "bottom-visible", "capitalize-first-letter-of-every-word", "capitalize-first-letter", "chain-asynchronous-functions", "check-for-palindrome", "chunk-array", "collatz-algorithm", "compact", "count-occurrences-of-a-value-in-array", "current-URL", "curry", "deep-flatten-array", "distance-between-two-points", "divisible-by-number", "drop-elements-in-array", "element-is-visible-in-viewport", "escape-regular-expression", "even-or-odd-number", "factorial", "fibonacci-array-generator", "fill-array", "filter-out-non-unique-values-in-an-array", "flatten-array-up-to-depth", "flatten-array", "get-days-difference-between-dates", "get-max-value-from-array", "get-min-value-from-array", "get-native-type-of-value", "get-scroll-position", "greatest-common-divisor-(GCD)", "group-by", "hamming-distance", "head-of-list", "hexcode-to-RGB", "initial-of-list", "initialize-array-with-range", "initialize-array-with-values", "is-array", "is-boolean", "is-function", "is-number", "is-string", "is-symbol", "last-of-list", "measure-time-taken-by-function", "median-of-array-of-numbers", "nth-element-of-array", "number-to-array-of-digits", "object-from-key-value-pairs", "object-to-key-value-pairs", "ordinal-suffix-of-number", "percentile", "pick", "pipe", "powerset", "promisify", "random-integer-in-range", "random-number-in-range", "redirect-to-URL", "reverse-a-string", "RGB-to-hexadecimal", "round-number-to-n-digits", "run-promises-in-series", "scroll-to-top", "shallow-clone-object", "shuffle-array", "similarity-between-arrays", "sleep", "sort-characters-in-string-(alphabetical)", "speech-synthesis-(experimental)", "standard-deviation", "sum-of-array-of-numbers", "swap-values-of-two-variables", "tail-of-list", "take-right", "take", "truncate-a-string", "unique-values-of-array", "URL-parameters", "UUID-generator", "validate-email", "validate-number", "value-or-default", "write-json-to-file"]
    

  3. Now, it’s time for the most important part of the code. The function to filter the array. Let’s break down the required function into small pieces.
    • Let’s call the function “updateResult”.
    • All functions generally have an input and an output. In this function, the input will be the what the user types in the search box. This will be the only argument the function takes. It won’t have any output but it will have an action i.e changing the view. So, it need not return anything.
      function updateResult(query) {
      }
      
    • Now, we need to call this function every time the user types something. The easiest way to do this is the “oninput” attribute of the “input” element. So, put an oninput attribute to our input box and pass its value.
      <input oninput="updateResult(this.value)" type="search" placeholder="Search..." />
      
    • Iterate through the array to linearly check each element if the entered words match the array elements. To check if it matches, you can use the Array.indexOf() function. If it returns -1 it doesn’t match. We need to call the indexOf() function f or each of the words the user enters. We can do that by using the split() and map() functions. Don’t forget to use String.toLowerCase() to ignore case sensitivity.
      function updateResult(query) {
          arr.map(function(algo){
              query.split(" ").map(function (word){
                  if(algo.toLowerCase().indexOf(word.toLowerCase()) != -1){
                  }
              })
          })
      }
      
    • Everytime the ‘if’ condition passes, we need to add the ‘algo’ to the result list in the html page. For this, we can create a DOM object of the list and update its ‘innerHTML’.
      function updateResult(query) {
          let resultList = document.querySelector(".result");
          arr.map(function(algo){
              query.split(" ").map(function (word){
                  if(algo.toLowerCase().indexOf(word.toLowerCase()) != -1){
                      resultList.innerHTML += `<li class="list-group-item">${algo}</li>`;
                  }
              })
          })
      }
      
    • This will keep adding items to the list as the function is called. The items will keep stacking up. To avoid this, we need to truncate the list at beginningning of the function itself. So, finally your code should look like this.
      function updateResult(query) {
          let resultList = document.querySelector(".result");
          resultList.innerHTML = "";
      
          arr.map(function(algo){
              query.split(" ").map(function (word){
                  if(algo.toLowerCase().indexOf(word.toLowerCase()) != -1){
                      resultList.innerHTML += `<li class="list-group-item">${algo}</li>`;
                  }
              })
          })
      }
      
  4. Include the ‘main.js’ file in index.html
  5. Open the index.html file in your browser. It will look something like this.
    Simple demo

Final thoughts

Wasn’t that easy?

I hope you understood how it works now. In this tutorial, we used simple linear search. This won’t always be feasible. When there are more elements in the array, better search algorithms need to be used. If you know of any good algorithms, please share in the comments below. Also, I will be hosting the code I wrote on GitHub. Feel free to make contributions.

You can see the live demo here.

Arjun Mahishi
4.6 5 votes
Article Rating
Subscribe
Notify of
guest

12 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
ostad
ostad
6 years ago

Hi
Thats a very neat code, but I found this little bug.
When u set “con con con con” as the query filter, the item “array-concatenation” is being added like 4 times to the final result. before an item being added we should check whether algo we’re working on is not in the results already to avoid creating redundant result.

Victor
5 years ago

Hi Arjun Mahishi,
Thanks for the tutorial, there is a little observation I want to make in this declaration: let resultList = document.querySelector(“.result”);

I believe you meant: let resultList = document.querySelector(“#result-list”);

A beginner might have trouble spotting this.

Paul
Paul
5 years ago

How would the code be adjusted to make this work but with images? And have all images hidden before searching? If possible of course!

Nguyen Duc Nhat Anh
Nguyen Duc Nhat Anh
5 years ago

This to enought to filter . fix bug duplicate source

function updateResult(query) {
let resultList = document.querySelector(“.result”);
resultList.innerHTML = “”;

arr.map(function(algo){

if(algo.toLowerCase().indexOf(query.toLowerCase()) != -1){
resultList.innerHTML += `<li class="list-group-item">${algo}</li>`;

})
})

}

Josh
Josh
4 years ago

Thank you, this is a lifesaver…

Joseph
Joseph
5 years ago

Hi, how would you trigger an action (say set the resultList.innerHTML to “Couldn’t find anything”) if there were no results found in the array?

Thanks

Joseph
Joseph
5 years ago

Hi, how would one make the result list show a message (e.g. “no results found”) if there are no results in the array that match the query?

oki
oki
3 years ago

Hi, is there a way to

  1. Hide all the content before searching and show only the matching results?
  2. Input the ‘sample results’ externally?

Thanks btw, this is something i really needed.

Last edited 3 years ago by oki
owen
3 years ago

can u just give me the whole html s i can coppie and past it

kalungi rasuli
kalungi rasuli
1 year ago

check the html code is messing class result, or either alter the js code to set and attribute to the element , i have instead inspected the code demo page to find out what is wrong with the example and found that.