Search code examples
javascriptmysqljsonfull-text-searchfuzzy-search

Filter/Search A Table Using Partial Match - HTML & Javascript


I have an HTML table which I am trying to filter using fuzzy search and partial matches. I have tried many JS libraries, but they don't seem to offer both of these filter options combined. I have tried FuzySort.js, FlexSearch.js, and others. Does anyone know of a library that can do this?

The foundation:

  • MySQL stores the data.
  • Front end displays the table.
  • Admins have a separate front-end lets them add/remove/edit the data to MySQL.
  • JavaScript to filter/sort/search the table client side on the front end.

Requirements:

  • Full text search
  • Fuzzy search
  • Partial matches.

Expected Results: If...

  • Table row #1 has the name "Name1"
  • Table row #2 has the name "Name2"
  • Table row #3 has the name "Name3"
  • And in the search bar, you type "Name1 Name3" it should display row 1 and 3

Current Results:

  • in the search bar, when you type "Name1 Name3" it displays no results.

Current Code

    function myFunction() {
  var input, filter, table, tr, td, i, txtValue;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  table = document.getElementById("myTable");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td")[1];
    if (td) {
      txtValue = td.textContent || td.innerText;
      if (txtValue.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }       
  }
}

Here is my JSFiddle: https://jsfiddle.net/h7p8bzs0/

Any help or direction is greatly appreciated. Does anyone have any suggestions for what library can achieve these results, or how I can tweak the JS code above to do this?

Ps: Sorry, I'm new and overwhelmed with the options of using JSON, Node.JS, Actual Databases, etc.


Solution

  • you might want to try the following Javascript:

    function myFunction() {
      const input = document.getElementById("myInput");
      const filters = input.value.toUpperCase().split(' '); // create several filters separated by space
      const table = document.getElementById("myTable");
      const tr = table.getElementsByTagName("tr");
    
      for (let i = 0; i < tr.length; i++) {
        const td = tr[i].getElementsByTagName("td")[1];
    
        if (td) {
          const txtValue = td.textContent || td.innerText;
            tr[i].style.display = "none"; // hide each row
            
          for (filter of filters) { // add the rows matching a filter
            if (txtValue.toUpperCase().indexOf(filter) > -1) {
              tr[i].style.display = "";        
            }
          }       
        }
      }
    }
    

    What happens here is that we create more than one filter string to match against, separated by a space. We hide each row as soon as we have at least one filter and add it again if it matches at least one of the filters.

    Oh and I restructered your variables a bit: We don't need declarators beforehand and we want to have them as let or const so that they aren't global.