【问题标题】:HTML Table search on each column Individually using JavaScript每列的 HTML 表格搜索单独使用 JavaScript
【发布时间】:2019-02-05 18:11:04
【问题描述】:

我有一张有 5 列的表格。以下代码将根据所有列过滤数据。我想过滤每一列的数据。例如:如果有 10 列,则 10 个搜索字段,以及如何使 HTML 部分动态化,以便在添加新列时不必再添加一个搜索文本字段。

<input id="myInput" type="text"  />

<script>
   function filterTable(event) {
    var filter = event.target.value.toUpperCase();
    var rows = document.querySelector("#myTable tbody").rows;

    for (var i = 1; i < rows.length; i++) {
        var Col1 = rows[i].cells[0].textContent.toUpperCase();
        var Col2 = rows[i].cells[1].textContent.toUpperCase();
        var Col3 = rows[i].cells[2].textContent.toUpperCase();
        var Col4 = rows[i].cells[3].textContent.toUpperCase();
        var Col5 = rows[i].cells[4].textContent.toUpperCase();
        if (Col1.indexOf(filter) > -1 || Col2.indexOf(filter) > -1 || Col3.indexOf(filter) > -1
          || Col4.indexOf(filter) > -1 || Col5.indexOf(filter) > -1) {
            rows[i].style.display = "";
        } else {
            rows[i].style.display = "none";
        }      
    }
}

document.querySelector(''#myInput'').addEventListener(''keyup'', filterTable, false);
</script>

我想拥有这样的功能:

【问题讨论】:

    标签: javascript html


    【解决方案1】:

    您可以循环遍历行,然后遍历列。 Array.from 方法允许您将元素列表转换为数组,以便您可以使用 Array.prototype.forEach 遍历子元素。

    您需要做的就是将每行的show 初始化为true。然后,如果任何 DOES NOT 列满足过滤条件,则将 show 设置为 false。循环遍历所有列后,根据show 的最终值显示行。

    编辑:确保您使用的是支持 ES6+ 的浏览器。在 MDN 网站上有一个可用于 Array.from 的 polyfill。

    function filterTable(event) {
      let filter = event.target.value.trim().toLowerCase();
      let rows = document.querySelector('#myTable tbody').rows;
      for (let i = 0; i < rows.length; i++) {
        let row = rows[i], show = false;
        if (filter.length > 0) {
          for (let j = 0; j < row.children.length; j++) {
            let col = row.children[j], text = col.textContent.toLowerCase();
            if (text.indexOf(filter) > -1) {
              show = true;
              continue;
            }
          }
        } else {
          show = true;
        }
        // Avoid using 'row.styledisplay' - https://stackoverflow.com/a/28028656/1762224
        // Avoid using 'row.visibility'   - rows do not collapse
        toggleClass(row, 'hidden-row', !show);
      }
    }
    
    function toggleClass(el, className, state) {
      if (el.classList) el.classList.toggle(className, state);
      else {
        var classes = el.className.split(' ');
        var existingIndex = classes.indexOf(className);
        if (state === undefined) {
          if (existingIndex > -1) classes.splice(existingIndex, 1)
          else classes.push(existingIndex);
        } else {
          if (!state) classes.splice(existingIndex, 1)
          else classes.push(existingIndex);
        }
        el.className = classes.join(' ');
      }
    }
    
    document.querySelector('#myInput').addEventListener('keyup', filterTable, false);
    body {
      padding: 8px;
    }
    .field label {
      font-weight: bold;
      margin-right: 0.25em;
    }
    #myTable {
      margin-top: 0.667em;
      width: 100%;
    }
    #myTable th {
      text-transform: capitalize;
    }
    .hidden-row {
      display: none;
    }
    <link href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" rel="stylesheet" />
    <div class="field"><label for="myInput">Filter:</label><input id="myInput" type="text" /></div>
    <table id="myTable" class="pure-table pure-table-horizontal">
      <thead>
        <tr>
          <th>name</th>
          <th>drink</th>
          <th>pizza</th>
          <th>movie</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Homer</td>
          <td>Squishie</td>
          <td>Magheritta</td>
          <td>The Avengers</td>
        </tr>
        <tr>
          <td>Marge</td>
          <td>Squishie</td>
          <td>Magheritta</td>
          <td>The Avengers</td>
        </tr>
        <tr>
          <td>Bart</td>
          <td>Squishie</td>
          <td>Pepperoni</td>
          <td>Black Dynamite</td>
        </tr>
        <tr>
          <td>Lisa</td>
          <td>Buzz Cola</td>
          <td>Pepperoni</td>
          <td>Iron Man</td>
        </tr>
        <tr>
          <td>Maggie</td>
          <td>Duff Beer</td>
          <td>Magheritta</td>
          <td>The Avengers</td>
        </tr>
        <tr>
          <td>Kent</td>
          <td>Duff Beer</td>
          <td>Hawaiian</td>
          <td>The Avengers</td>
        </tr>
      </tbody>
    </table>

    搜索字段示例

    populateTable(document.getElementById('simpsons'), getData());
    
    function dataFields(data) {
      return data.reduce((r, x) => Object.keys(x).reduce((s, k) => s.indexOf(k) === -1 ? s.concat(k) : s, r), []);
    }
    
    /* Can be useful if working with raw JSON data */
    function searchCriteria(fields) {
      return Array.from(fields).reduce((o, field) => {
        return Object.assign(o, { [field.getAttribute('placeholder')] : field.value });
      }, {});
    }
    
    function onFilter(e) {
      let table = e.target.parentElement.parentElement.parentElement.parentElement;
      let fields = table.querySelectorAll('thead tr th input');
      let criteria = searchCriteria(fields); // Unused, but useful if filtering bindable data
      let searchText = Array.from(fields).map(field => field.value.trim());
      Array.from(table.querySelectorAll('tbody tr')).forEach(row => {
        let hideRow = false;
        Array.from(row.children).forEach((col, index) => {
          var value = col.innerHTML.trim().toLowerCase();
          var search = searchText[index].toLowerCase();
          if (search.length > 0) {
            if (!value.startsWith(search)) { /* or value.indexOf(search) === -1 */
              hideRow = true;
              return;
            }
          }
        });
        row.classList.toggle('hidden-row', hideRow);
      });
    }
    
    function populateTable(table, data) {
      let fields = dataFields(data);
      let thead = document.createElement('THEAD');
      let tr = document.createElement('TR');
      fields.forEach(field => {
        let th = document.createElement('TH');
        th.innerHTML = field;
        tr.appendChild(th);
      });
      thead.appendChild(tr);
      let tbody = document.createElement('TBODY');
      tr = document.createElement('TR');
      fields.forEach(field => {
        let th = document.createElement('TH');
        let input = document.createElement('INPUT');
        input.setAttribute('placeholder', field);
        input.addEventListener('keyup', onFilter);
        th.append(input);
        tr.appendChild(th);
      });
      thead.appendChild(tr);
      data.forEach(record => {
        let tr = document.createElement('TR');
        fields.forEach(field => {
          let td = document.createElement('TD');
          td.innerHTML = record[field];
          tr.appendChild(td);
        });
        tbody.append(tr);
      });
      table.appendChild(thead);
      table.appendChild(tbody);
    }
    
    function getData() {
      return [{
        "name": "Homer",
        "drink": "Squishie",
        "pizza": "Magheritta",
        "movie": "The Avengers"
      }, {
        "name": "Marge",
        "drink": "Squishie",
        "pizza": "Magheritta",
        "movie": "The Avengers"
      }, {
        "name": "Bart",
        "drink": "Squishie",
        "pizza": "Pepperoni",
        "movie": "Black Dynamite"
      }, {
        "name": "Lisa",
        "drink": "Buzz Cola",
        "pizza": "Pepperoni",
        "movie": "Iron Man"
      }, {
        "name": "Maggie",
        "drink": "Duff Beer",
        "pizza": "Magheritta",
        "movie": "The Avengers"
      }, {
        "name": "Kent",
        "drink": "Duff Beer",
        "pizza": "Hawaiian",
        "movie": "The Avengers"
      }];
    }
    table {
      border-collapse: collapse;
      width: 100%;
    }
    table thead tr th {
      text-transform: capitalize;
    }
    table thead tr:last-child {
      background: #eaeaea;
      border-bottom: 4px double #cbcbcb;
    }
    table thead tr th input {
      width: 100%;
    }
    table tbody tr:nth-child(even) {
      background-color: #f2f2f2;
    }
    table tbody tr.hidden-row {
      display: none;
    }
    <link href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" rel="stylesheet" />
    <table id="simpsons" class="pure-table pure-table-horizontal"></table>

    浏览器兼容性

    function onFilter(e) {
      var table = e.target.parentElement.parentElement.parentElement.parentElement;
      console.log(table);
      var fields = table.querySelectorAll('thead tr th input');
      console.log(fields);
      var searchText = Array.from(fields).map(function (field) {
        return field.value.trim();
      });
      console.log(searchText);
      Array.from(table.querySelectorAll('tbody tr')).forEach(function (row) {
        var hideRow = false;
        Array.from(row.children).forEach(function (col, index) {
          var value = col.innerHTML.trim().toLowerCase();
          console.log(value);
          var search = searchText[index].toLowerCase();
          console.log(search);
          if (search.length > 0) {
            if (value.indexOf(search) === -1) {
              hideRow = true;
              return;
            }
          }
        });
        row.classList.toggle('hidden-row', hideRow);
      });
    }
    

    【讨论】:

    • 谢谢,请您重新审视这个问题。我已经用所需的输出屏幕截图对其进行了更新。
    • @steve 我实现了一个搜索行的示例。
    • @steve 您可以使用value.indexOf(search) === -1 来测试搜索在值“内”是否存在。
    • 我已经更改了代码,但仍然不支持 array.from foreach 是否有任何替代...请查看编辑后的代码
    • @steve 如果您使用的是 IE,您将不得不使用 for 循环并通过子级索引以老式的方式遍历子级。你应该能够很容易地做到这一点。我可以稍后再回顾一下。您也可以将其转换为 jQuery。
    【解决方案2】:

    您所要做的就是使用 for 循环迭代 .cells 数组:

    对于这个例子,我使用了一个变量来确定是否应该显示该行。

    function filterTable(event) {
      var filter = event.target.value.toUpperCase();
      var rows = document.querySelector("#myTable tbody").rows;
    
      for (var i = 1; i < rows.length; i++) {
        // Placeholder to indicate if a row matches the given query.
        var shouldShowRow = false;
        // Loop over all the cells in this row.
        for (var k = 0; k < rows[i].cells.length) {
          // Check to see if this cell in this row matches the query.
          if (rows[i].cells[k].textContent.toUpperCase().indexOf(filter) > -1) {
            // Yes, this cell matches, therefore this entire row matches.
            // Flip the show row boolean to indicate that we need to show.
            shouldShowRow = true;
            // Because this cell matches, we do not need to check any more cells.
            break;
          }
        }
        // Change the display on the row if we need to.
        if (shouldShowRow) {
          rows[i].style.display = "";
        } else rows[i].style.display = "none";
      }
    }

    【讨论】:

      【解决方案3】:

      你可以使用数组。 首先将col 映射到数组colArr,然后使用一些可以匹配的内容,可以将filter 的内容与cols 的内容匹配。

      for (var i = 1; i < rows.length; i++) {
        let colArr = new Array(5).fill(0).map((e,index)=> rows[i].cells[index].textContent.toUpperCase();) 
           if (colArr.some(e=> e.indexOf(filter) > -1 ) {
               rows[i].style.display = "";
              } else {
                rows[i].style.display = "none";
              }
          }) 
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-05-01
        • 2018-03-28
        • 2021-06-22
        • 2011-03-03
        • 2016-07-07
        • 1970-01-01
        • 2021-03-24
        相关资源
        最近更新 更多