如何对 HTML 表格执行实时搜索和过滤

IT技术 javascript jquery html
2021-02-03 15:44:47

我一直在谷歌搜索和搜索 Stack Overflow 一段时间,但我无法解决这个问题。

我有一个标准的 HTML 表格,其中包含水果。像这样:

<table>
   <tr>
      <td>Apple</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Grapes</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Orange</td>
      <td>Orange</td>
   </tr>
</table>

在此之上我有一个文本框,我想在用户键入时搜索该表。因此,如果他们打字Gre,表格的橙色行就会消失,留下苹果和葡萄。如果他们继续打字Green Gr,Apple 行应该会消失,只留下葡萄。我希望这很清楚。

而且,如果用户从文本框中删除他们的部分或全部查询,我希望现在与查询匹配的所有行重新出现。

虽然我知道如何在 jQuery 中删除表行,但我对如何进行搜索和基于此有选择地删除行知之甚少。有没有简单的解决方案?还是插件?

如果有人能指出我正确的方向,那就太好了。

谢谢你。

6个回答

我创建了这些示例。

简单的indexOf搜索

var $rows = $('#table tr');
$('#search').keyup(function() {
    var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();

    $rows.show().filter(function() {
        var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
        return !~text.indexOf(val);
    }).hide();
});

演示http : //jsfiddle.net/7BUmG/2/

正则表达式搜索

使用正则表达式的更高级功能将允许您按行中的任何顺序搜索单词。如果您键入apple green,它将起作用green apple

var $rows = $('#table tr');
$('#search').keyup(function() {

    var val = '^(?=.*\\b' + $.trim($(this).val()).split(/\s+/).join('\\b)(?=.*\\b') + ').*$',
        reg = RegExp(val, 'i'),
        text;

    $rows.show().filter(function() {
        text = $(this).text().replace(/\s+/g, ' ');
        return !reg.test(text);
    }).hide();
});

演示http : //jsfiddle.net/dfsq/7BUmG/1133/

去抖

当您通过搜索多行和多列实现表过滤时,考虑性能和搜索速度/优化非常重要。简单地说你不应该在每次击键时都运行搜索功能,这是没有必要的。为防止过滤运行过于频繁,您应该对其进行去抖动。上面的代码示例将变为:

$('#search').keyup(debounce(function() {
    var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
    // etc...
}, 300));

您可以选择任何去抖动实现,例如从 Lodash _.debounce,或者您可以使用像我在下一个演示中使用的非常简单的东西(从这里去抖动):http: //jsfiddle.net/7BUmG/6230/http:// /jsfiddle.net/7BUmG/6231/

@JoshP 不,只需要 jQuery。只需确保您在 DOMReady 中或在加载 HTML 之后运行您的代码。
2021-03-14 15:44:47
我建议增强这种方法,因为它非常消耗资源。将所有精炼后的字符串放入具有两个字段的对象数组中:对<tr>DOMElement的引用和字符串。这样,keyup()可以搜索这些字符串(速度更快)并准备好操作相应的行。第一个昂贵的设置程序应该在加载后立即执行一次。所有这些更改都只是小修复,实际的中心部分仍然如此答案中所示。这种方法也是可行的,而且很容易在没有 jQuery 的情况下实现。
2021-04-03 15:44:47
@confusedMind 使用$('#table tr:not(:first)')选择器。
2021-04-03 15:44:47
@JoshP Sctipt 适用于所有行。如果您只想过滤内部的那些,<tbody>您应该更改为var $rows = $('#id-of-your-table tbody tr');.
2021-04-04 15:44:47
我敢绿色这个东西,但是如果我想将其纳入我的表这个,我只需要改变#tableid我的表?是否需要进行额外的更改来处理<thead><tbody>标记?我已经包含了来自 jsfiddle 链接的脚本和 html,更改了#id,但我没有过滤。
2021-04-05 15:44:47

我有一个 jquery 插件。它也使用 jquery-ui。你可以在这里看到一个例子 http://jsfiddle.net/tugrulorhan/fd8KB/1/

$("#searchContainer").gridSearch({
            primaryAction: "search",
            scrollDuration: 0,
            searchBarAtBottom: false,
            customScrollHeight: -35,
            visible: {
                before: true,
                next: true,
                filter: true,
                unfilter: true
            },
            textVisible: {
                before: true,
                next: true,
                filter: true,
                unfilter: true
            },
            minCount: 2
        });

这是在 HTML 表格中搜索同时覆盖所有表格表格中的所有 td、tr)、纯 javascript并尽可能的最佳解决方案

<input id='myInput' onkeyup='searchTable()' type='text'>

<table id='myTable'>
   <tr>
      <td>Apple</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Grapes</td>
      <td>Green</td>
   </tr>
   <tr>
      <td>Orange</td>
      <td>Orange</td>
   </tr>
</table>

<script>
function searchTable() {
    var input, filter, found, table, tr, td, i, j;
    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");
        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";
        }
    }
}
</script>
为了防止表格标题行消失,将 id 添加到该行,如:<tr id='tableHeader'> 并将最后的 else 语句更改为: if (tr[i].id != 'tableHeader'){tr[i ].style.display = "none";} 问题中没有提到它,但我希望它涵盖它以使其全面。
2021-03-13 15:44:47
与其使用 != 比较 id,我建议将最后的 else 更改为: } else if (!tr[i].id.match('^tableHeader')) { 这允许一个表有多个表,每个表带有自己的标题。需要做更多的工作来通过传入表 ID 来参数化 searchTable 函数。
2021-04-09 15:44:47

纯 Javascript 解决方案:

适用于所有列和不区分大小写:

function search_table(){
  // Declare variables 
  var input, filter, table, tr, td, i;
  input = document.getElementById("search_field_input");
  filter = input.value.toUpperCase();
  table = document.getElementById("table_id");
  tr = table.getElementsByTagName("tr");

  // Loop through all table rows, and hide those who don't match the search query
  for (i = 0; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td") ; 
    for(j=0 ; j<td.length ; j++)
    {
      let tdata = td[j] ;
      if (tdata) {
        if (tdata.innerHTML.toUpperCase().indexOf(filter) > -1) {
          tr[i].style.display = "";
          break ; 
        } else {
          tr[i].style.display = "none";
        }
      } 
    }
  }
}

我发现 dfsq 的回答其评论非常有用。我做了一些适用于我的小修改(我把它张贴在这里,以防对其他人有用)。

  1. 使用class钩,而不是表元素tr
  2. class在显示/隐藏父项时搜索/比较子项中的文本
  3. 通过仅将$rows文本元素存储到数组中一次(并避免$rows.length时间计算)来提高效率

var $rows = $('.wrapper');
var rowsTextArray = [];

var i = 0;
$.each($rows, function () {
    rowsTextArray[i] = ($(this).find('.number').text() + $(this).find('.fruit').text())
        .replace(/\s+/g, '')
        .toLowerCase();
    i++;
});

$('#search').keyup(function() {
  var val = $.trim($(this).val()).replace(/\s+/g, '').toLowerCase();
  $rows.show().filter(function(index) {
    return (rowsTextArray[index].indexOf(val) === -1);
  }).hide();
});
span {
  margin-right: 0.2em;
}
<input type="text" id="search" placeholder="type to search" />

<div class="wrapper"><span class="number">one</span><span class="fruit">apple</span></div>
<div class="wrapper"><span class="number">two</span><span class="fruit">banana</span></div>
<div class="wrapper"><span class="number">three</span><span class="fruit">cherry</span></div>
<div class="wrapper"><span class="number">four</span><span class="fruit">date</span></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

那是因为它只读取“水果”而不是“数字”。我已经更新了。当我还是一个初学者时,我写了这个答案。
2021-03-14 15:44:47
不知道为什么即使“一、二、四”中有 o 也不搜索“o”?
2021-03-21 15:44:47
大声笑,每个人都做了一些好事,但在初学者时却没有那么好😊
2021-04-09 15:44:47
甚至“w”,我猜正则表达式没有搜索很多值
2021-04-11 15:44:47