Home > database >  How to assign multiple possible search value to a <td> when searching/filtering thru it?
How to assign multiple possible search value to a <td> when searching/filtering thru it?

Time:03-09

I'm trying to assign multiple hidden values to a <td> of a table so that when I search through it, it will still show that value. Kind of like an alt text for tables.

As an example, if I'm building a table of medicines, I want to be able to search for every possible brand names of that medicine.

Here's what I've got so far:

function myFunction() {
  var input, filter, table, tr, td, i,alltables;
    alltables = document.querySelectorAll("table[data-name=mytable]");
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  alltables.forEach(function(table){
      tr = table.getElementsByTagName("tr");
      for (i = 0; i < tr.length; i  ) {
        td = tr[i].getElementsByTagName("td")[0];
        if (td) {
          if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
            tr[i].style.display = "";
          } else {
            tr[i].style.display = "none";
          }
        }       
      }
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h2>Meds</h2>

<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">

<table id="myTable"  data-name="mytable">
  <tr >
    <th style="width:60%;">Drug name</th>
    <th style="width:40%;">Dosage</th>
  </tr>
  <tr>
    <td>Asprin</td>
    <td>1mg</td>
  </tr>
  <tr>
    <td>Fentanyl</td>
    <td>12mg</td>
  </tr>
  <tr>
    <td>Ibuprofen</td>
    <td>1mg</td>
  </tr>
  <tr>
    <td>Paracetamol</td>
    <td>2mg</td>
  </tr>
</table>

I want to be able to search for Tylenol, Mapap or Panadol(a brand name of paracetamol) and still show paracetamol in the result. If I'm using an alt text(as an example because I don't know what to do) it would look like this:

<table id="myTable"  data-name="mytable">
  <tr >
    <th style="width:60%;">Drug name</th>
    <th style="width:40%;">Dosage</th>
  </tr>
  <tr>
    <td>Asprin</td>
    <td>1mg</td>
  </tr>
  <tr>
    <td>Fentanyl</td>
    <td>12mg</td>
  </tr>
  <tr>
    <td alt="Advil, Motrin, IBU">Ibuprofen</td>
    <td>1mg</td>
  </tr>
  <tr>
    <td alt="Tylenol, Mapap or Panadol">Paracetamol</td>
    <td>2mg</td>
  </tr>
</table>

CodePudding user response:

If you tweak your HTML, like so:

<table id="myTable"  data-name="mytable">
  <tr >
    <th style="width:60%;">Drug name</th>
    <th style="width:40%;">Dosage</th>
  </tr>
  <tr >
    <td>Asprin</td>
    <td>1mg</td>
  </tr>
  <tr >
    <td>Fentanyl</td>
    <td>12mg</td>
  </tr>
  <tr >
    <td data-alt="Advil, Motrin, IBU">Ibuprofen</td>
    <td>1mg</td>
  </tr>
  <tr >
    <td data-alt="Tylenol, Mapap or Panadol">Paracetamol</td>
    <td>2mg</td>
  </tr>
</table>

Then you could just apply the filter on the row, rather than the cell. Something like this:

function myFunction() {
  var input, filter, table, tr, td, i,alltables;
    alltables = document.querySelectorAll("table[data-name=mytable]");
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  alltables.forEach(function(table){
      tr = table.querySelectorAll("tr.datarow");
      for (i = 0; i < tr.length; i  ) {
          if (tr[i].innerHTML.toUpperCase().indexOf(filter) > -1) {
            tr[i].style.display = "";
          } else {
            tr[i].style.display = "none";
          }
               
      }
  });
}

CodePudding user response:

I'm assuming that there will be many data's, So going through each element constantly will be a performance issue. My suggestion would be to specify a size of input after which the search will begin.

Here's my solution

let searchBox = document.querySelector("input"),
  table = document.querySelector("table");

searchBox.addEventListener(
  "input",
  debounce(function () {
    const val = searchBox.value.toLowerCase(),
      tableRows = table.querySelectorAll("tbody tr");

    if (val.length >= 3) {
      tableRows.forEach((row) => {
        let brands = row.dataset.brands;
        if (brands.includes(val)) {
          row.style.display = "table-row";
        } else {
          row.style.display = "none";
        }
      });
    } else {
      tableRows.forEach((row) => {
        row.style.display = "table-row";
      });
    }
  }, 600)
);
function debounce(func, wait, immediate) {
  var timeout;
  return function () {
    var context = this,
      args = arguments;
    var later = function () {
      timeout = null;
      if (!immediate) {
        func.apply(context, args);
      }
    };
    var callout = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callout) {
      func.apply(context, args);
    }
  };
}
<input type="search" placeholder="Type in a medicine name">
<table id="medTable">
  <thead>
    <tr>
      <th>Drug Name</th>
      <th>Dosage</th>
    </tr>
  </thead>
  <tbody>
    <tr data-brands = "a,b,c">
      <td>Aspirin</td>
      <td>1mg</td>
    </tr>
    <tr data-brands = "d,e,f">
      <td>Fentanyl</td>
      <td>12mg</td>
    </tr>
    <tr data-brands = "g,h,i">
      <td>Ibuprofen</td>
      <td>1mg</td>
    </tr>
    <tr data-brands = "j,k,l">
      <td>Paracetamol</td>
      <td>2mg</td>
    </tr>
  </tbody>
</table>

  • Related