1

I have this html table which will later be replaced by a for loop. I want to sum the data I get in Number table, after applying lookup filters.

Currently the sum remains fixed for all values ​​and does not consider the filter.

function searchTable() {
  var filter, found, table, tr, td, i, j;
  //input = document.getElementById("search");
  //input2 = document.getElementById("search2");
  filter = input.value.toUpperCase();
  table = document.getElementById("displaytable");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td");
    for (j = 0; j < td.length; j++) {
      if (td[j].innerHTML.toUpperCase().indexOf(filter) > -1) {
        found = true;
      }
    }
    if (found) {
      tr[i].style.display = "";
      found = false;
    } else {
      tr[i].style.display = "none";
    }
  }
  var cls = document.getElementById("displaytable").getElementsByTagName("td");
  var sum = 0;
  for (var i = 0; i < cls.length; i++) {
    if (cls[i].className == "countable" && cls[i].closest("tr").style.display != "none") {
      sum += isNaN(cls[i].innerHTML) ? 0 : parseInt(cls[i].innerHTML);
    }
  }
  document.getElementById('total').innerHTML = sum;

}
var cls = document.getElementById("displaytable").getElementsByTagName("td");
var sum = 0;
for (var i = 0; i < cls.length; i++) {
  if (cls[i].className == "countable") {
    sum += isNaN(cls[i].innerHTML) ? 0 : parseInt(cls[i].innerHTML);
  }
}
document.getElementById('total').innerHTML += sum;
<head>

  <!--  <link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.11.1/css/jquery.dataTables.min.css"> -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="//cdn.datatables.net/1.11.1/js/jquery.dataTables.min.js"></script>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
  <link href="https://unpkg.com/bootstrap-table@1.21.2/dist/bootstrap-table.min.css" rel="stylesheet">
  <script src="https://unpkg.com/bootstrap-table@1.21.2/dist/bootstrap-table.min.js"></script>
  <script src="https://unpkg.com/bootstrap-table@1.21.2/dist/extensions/filter-control/bootstrap-table-filter-control.min.js"></script>

</head>
<!-- <input type="text" id="search" onkeyup='searchTable()' placeholder="Type to search">
<input type="text" id="search2" onkeyup='searchTable()' placeholder="Type to search"> -->
<!-- <input class="form-control" onkeyup='searchTable()' id="search" type="text" placeholder="Search.."> -->
<table class="table responsive table table-striped" data-toggle="table" data-filter-control="true" data-show-jump-to="true" data-pagination="true" data-show-columns="true">
  <thead>
    <tr>
      <th scope="col" data-field="name" data-filter-control="input">Name</th>
      <th scope="col" data-field="surname" data-filter-control="input">Surname</th>
      <th scope="col" data-field="number" data-filter-control="input">Number</th>
    </tr>
  </thead>
  <tbody id="displaytable">
    <tr>
      <td>John</td>
      <td>Tidor</td>
      <td class="countable">5</td>
    </tr>
    <tr>
      <td>Marc</td>
      <td>Tidor</td>
      <td class="countable">5</td>
    </tr>
    <tr>
      <td>Tom</td>
      <td>Cruise</td>
      <td class="countable">4</td>
    </tr>
    <tr>
      <td>Jordan</td>
      <td>Michael</td>
      <td class="countable">7</td>
    </tr>
    <tr>
      <td>Marc</td>
      <td>Michael</td>
      <td class="countable">3</td>
    </tr>
    <tr>
      <td>Marc</td>
      <td>Michael</td>
      <td class="countable">1</td>
    </tr>
  </tbody>
  <!-- <tfoot class="shown">
        <tr>
            <td colspan="5">Total:</td>
            <td id="total"></td>
        </tr>
    </tfoot> -->
</table>

<table>
  <tfoot class="shown">
    <tr>
      <td colspan="5">Total:</td>
      <td id="total"></td>
    </tr>
</table>
Barmar
  • 741,623
  • 53
  • 500
  • 612

1 Answers1

1

This cannot work because you have just one filter in your function. And remove the onclick, it's better to use EventListeners.

So, here at start You start with an empty list because none of the input fields are filled.

EDIT 1 : And yes, avoid var! You may take a look on the first snippet, but the second is an update.

EDIT 2 : Check at the second snippet because in the first one if you type "M" Tom will also appear because it contains a "m"!!!

EDIT 3 : Added a third snippet to avoid searches in multiple fields at the same time, so you don't have problems that may occur in the two first snippets.

By keeping the three solutions, you can have an idea of the inconveniences of the two first proposals.

        let filter1, filter2;
        document.addEventListener("DOMContentLoaded", init);
        
        function init(){
          filter1 = document.getElementById("search");
          filter2 = document.getElementById("search2");
          filter1.addEventListener("keyup", searchTable);
          filter2.addEventListener("keyup", searchTable);
          searchTable();
        }

        function searchTable() {
          let found, table, tr, td, i;
          filter1 = document.getElementById("search").value.toUpperCase();
          filter2 = document.getElementById("search2").value.toUpperCase();
          table = document.getElementById("displaytable");
          tr = table.getElementsByTagName("tr");
          for (i = 0; i < tr.length; i++) {
            td = tr[i].getElementsByTagName("td");
            found = false;
            if (
              (filter1 && td[0].innerHTML.toUpperCase().indexOf(filter1) > -1) ||
              (filter2 && td[1].innerHTML.toUpperCase().indexOf(filter2) > -1)
            ) {
              found = true;
            }
            tr[i].style.display = found ? "" : "none";
          }
          updateTotal();
        }

        function updateTotal() {
          let cls = document.getElementById("displaytable").getElementsByTagName("td");
          let sum = 0;
          let originalList = false;
          for (i = 0; i < cls.length; i++) {
            if (
              cls[i].className == "countable" &&
              cls[i].closest("tr").style.display != "none"
            ) {
              sum += isNaN(cls[i].innerHTML) ? 0 : parseInt(cls[i].innerHTML);
              originalList = true;
            }
          }
          document.getElementById("total").innerHTML = originalList ? sum : "";
        }
    <input type="text" id="search" placeholder="Search Name">
    <input type="text" id="search2" placeholder="Search Surname">
    <!-- <input class="form-control" onkeyup='searchTable()' id="search" type="text" placeholder="Search.."> -->
    <table class="table responsive table table-striped" data-toggle="table" data-filter-control="true" data-show-jump-to="true" data-pagination="true" data-show-columns="true">
      <thead>
        <tr>
          <th scope="col" data-field="name" data-filter-control="input">Search by Name</th>
          <th scope="col" data-field="surname" data-filter-control="input">Search by Surname</th>
          <th scope="col" data-field="number" data-filter-control="input">Number</th>
        </tr>
      </thead>
      <tbody id="displaytable">
        <tr>
          <td>John</td>
          <td>Tidor</td>
          <td class="countable">5</td>
        </tr>
        <tr>
          <td>Marc</td>
          <td>Tidor</td>
          <td class="countable">5</td>
        </tr>
        <tr>
          <td>Tom</td>
          <td>Cruise</td>
          <td class="countable">4</td>
        </tr>
        <tr>
          <td>Jordan</td>
          <td>Michael</td>
          <td class="countable">7</td>
        </tr>
        <tr>
          <td>Marc</td>
          <td>Michael</td>
          <td class="countable">3</td>
        </tr>
        <tr>
          <td>Marc</td>
          <td>Michael</td>
          <td class="countable">1</td>
        </tr>
      </tbody>

    </table>

    <table>
      <tfoot class="shown">
        <tr>
          <td colspan="5">Total:</td>
          <td id="total"></td>
        </tr>
      </tfoot>
    </table>

Here's an edit that is more accurate as I say in my EDIT 2 : So : "M" will display all the names that begins with "M". "Mi" will display "Michael", "Michel", "Miranda". and "MIC" only "Michael" and "Michel"

        let filter1, filter2, filter3;

        document.addEventListener("DOMContentLoaded", init);

        function init() {
          filter1 = document.getElementById("search").value.toUpperCase();
          filter2 = document.getElementById("search2").value.toUpperCase();
          filter3 = document.getElementById("search3").value.toUpperCase();

          document.getElementById("search").addEventListener("keyup", searchTable);
          document.getElementById("search2").addEventListener("keyup", searchTable);
          document.getElementById("search3").addEventListener("keyup", searchTable);

          searchTable();
        }

        function searchTable() {
          let found, table, tr, td, i;
          filter1 = document.getElementById("search").value.toUpperCase();
          filter2 = document.getElementById("search2").value.toUpperCase();
          filter3 = document.getElementById("search3").value.toUpperCase();

          table = document.getElementById("displaytable");
          tr = table.getElementsByTagName("tr");

          for (i = 0; i < tr.length; i++) {
            if (tr[i].getElementsByTagName("th").length > 0) {
              continue;
            }
            td = tr[i].getElementsByTagName("td");
            found = false;

            if (
              (filter1 && td[0].textContent.toUpperCase().startsWith(filter1.trim())) ||
              (filter2 && td[1].textContent.toUpperCase().includes(filter2.trim())) ||
              (filter3 && td[2].textContent.trim().toUpperCase() === filter3.trim())
            ) {
              found = true;
            }

            tr[i].style.display = found ? "" : "none";
          }

          updateTotal();
        }

        function updateTotal() {
          let cls = document.getElementById("displaytable").getElementsByTagName("td");
          let sum = 0;
          let originalList = false;

          for (var i = 0; i < cls.length; i++) {
            if (cls[i].className == "countable" && cls[i].closest("tr").style.display != "none") {
              sum += isNaN(cls[i].innerHTML) ? 0 : parseInt(cls[i].innerHTML);
              originalList = true;
            }
          }

          document.getElementById("total").innerHTML = originalList ? sum : "";
        }
    <input type="text" id="search" placeholder="Search Name">
    <input type="text" id="search2" placeholder="Search Surname">
    <input type="text" id="search3" placeholder="Search Value">
    <table class="table responsive table table-striped" data-toggle="table" data-filter-control="true" data-show-jump-to="true" data-pagination="true" data-show-columns="true">
      <thead>
        <tr>
          <th scope="col" data-field="name" data-filter-control="input">Search by Name</th>
          <th scope="col" data-field="surname" data-filter-control="input">Search by Surname</th>
          <th scope="col" data-field="number" data-filter-control="input">Search by value</th>
        </tr>
      </thead>
      <tbody id="displaytable">
        <tr>
          <td>John</td>
          <td>Tidor</td>
          <td class="countable">5</td>
        </tr>
        <tr>
          <td>Marc</td>
          <td>Tidor</td>
          <td class="countable">5</td>
        </tr>
        <tr>
          <td>Tom</td>
          <td>Cruise</td>
          <td class="countable">4</td>
        </tr>
        <tr>
          <td>Jordan</td>
          <td>Michael</td>
          <td class="countable">7</td>
        </tr>
        <tr>
          <td>Marc</td>
          <td>Michael</td>
          <td class="countable">3</td>
        </tr>
        <tr>
          <td>Marc</td>
          <td>Michael</td>
          <td class="countable">1</td>
        </tr>
        <tr>
          <td>Miranda</td>
          <td>Mimi</td>
          <td class="countable">10</td>
        </tr>
        <tr>
          <td>Michel</td>
          <td>Mitch</td>
          <td class="countable">1</td>
        </tr>
        <tr>
          <td>John</td>
          <td>Doe</td>
          <td class="countable">0</td>
        </tr>
      </tbody>

    </table>

    <table>
      <tfoot class="shown">
        <tr>
          <td colspan="5">Total:</td>
          <td id="total"></td>
        </tr>
      </tfoot>
    </table>

Searches in the different fields at the same time may not working as expected! So I suggest you to reset all the fields to "" when you select a field to fill like in this third EDIT

Third snippet :

        let filter1, filter2, filter3;
        let searchInput1;
        let searchInput2;
        let searchInput3;
        let filters;

        document.addEventListener("DOMContentLoaded", init);

        function init() {
          filter1 = document.getElementById("search");
          filter2 = document.getElementById("search2");
          filter3 = document.getElementById("search3");
            
          filters = [filter1, filter2, filter3];

          searchInput1 = document.getElementById("search");
          searchInput2 = document.getElementById("search2");
          searchInput3 = document.getElementById("search3");

          filter1.addEventListener("focus", () => resetOtherFields(filter1));
          filter2.addEventListener("focus", () => resetOtherFields(filter2));
          filter3.addEventListener("focus", () => resetOtherFields(filter3));

          filter1.addEventListener("keyup", searchTable);
          filter2.addEventListener("keyup", searchTable);
          filter3.addEventListener("keyup", searchTable);

          searchTable();
        }

        function resetOtherFields(currentField) {
          filters.forEach((field) => {
            if (field !== currentField) {
              field.value = "";
            }
          });

          searchTable();
        }

        function searchTable() {
          let found, table, tr, td, i;
          filter1 = searchInput1.value.toUpperCase();
          filter2 = searchInput2.value.toUpperCase();
          filter3 = searchInput3.value.toUpperCase();

          table = document.getElementById("displaytable");
          tr = table.getElementsByTagName("tr");

          for (i = 0; i < tr.length; i++) {
            if (tr[i].getElementsByTagName("th").length > 0) {
              continue;
            }
            td = tr[i].getElementsByTagName("td");
            found = false;

            if (
              (filter1 && td[0].textContent.toUpperCase().startsWith(filter1.trim())) ||
              (filter2 && td[1].textContent.toUpperCase().startsWith(filter2.trim())) ||
              (filter3 && td[2].textContent.trim().toUpperCase() === filter3.trim())
            ) {
              found = true;
            }

            tr[i].style.display = found ? "" : "none";
          }

          updateTotal();
        }
        
        function updateTotal() {
          let cls = document.getElementById("displaytable").getElementsByTagName("td");
          let sum = 0;
          let originalList = false;

          for (var i = 0; i < cls.length; i++) {
            if (cls[i].className == "countable" && cls[i].closest("tr").style.display != "none") {
              sum += isNaN(cls[i].innerHTML) ? 0 : parseInt(cls[i].innerHTML);
              originalList = true;
            }
          }

          document.getElementById("total").innerHTML = originalList ? sum : "";
        }
    <input type="text" id="search" placeholder="Search Name">
    <input type="text" id="search2" placeholder="Search Surname">
    <input type="text" id="search3" placeholder="Search Value">
    <table class="table responsive table table-striped" data-toggle="table" data-filter-control="true" data-show-jump-to="true" data-pagination="true" data-show-columns="true">
      <thead>
        <tr>
          <th scope="col" data-field="name" data-filter-control="input">Search by Name</th>
          <th scope="col" data-field="surname" data-filter-control="input">Search by Surname</th>
          <th scope="col" data-field="number" data-filter-control="input">Search by value</th>
        </tr>
      </thead>
      <tbody id="displaytable">
        <tr>
          <td>John</td>
          <td>Tidor</td>
          <td class="countable">5</td>
        </tr>
        <tr>
          <td>Marc</td>
          <td>Tidor</td>
          <td class="countable">5</td>
        </tr>
        <tr>
          <td>Tom</td>
          <td>Cruise</td>
          <td class="countable">4</td>
        </tr>
        <tr>
          <td>Jordan</td>
          <td>Michael</td>
          <td class="countable">7</td>
        </tr>
        <tr>
          <td>Marc</td>
          <td>Michael</td>
          <td class="countable">3</td>
        </tr>
        <tr>
          <td>Marc</td>
          <td>Michael</td>
          <td class="countable">1</td>
        </tr>
        <tr>
          <td>Miranda</td>
          <td>Mimi</td>
          <td class="countable">10</td>
        </tr>
        <tr>
          <td>Michel</td>
          <td>Mitch</td>
          <td class="countable">1</td>
        </tr>
        <tr>
          <td>John</td>
          <td>Doe</td>
          <td class="countable">0</td>
        </tr>
        <tr>
          <td>Michael</td>
          <td>Jackson</td>
          <td class="countable">4</td>
        </tr>
      </tbody>

    </table>

    <table>
      <tfoot class="shown">
        <tr>
          <td colspan="5">Total:</td>
          <td id="total"></td>
        </tr>
      </tfoot>
    </table>

So, now the reset is done when you change the field into you want to check a value.

tatactic
  • 1,379
  • 1
  • 9
  • 18
  • Sorry for all those edits but I was in the mood and wanted something efficient. I hope this will help you to understand some mistakes I made in my two first answers edit after edit. – tatactic Jun 08 '23 at 23:18