【问题标题】:How to filter multiple tables by td content如何通过 td 内容过滤多个表
【发布时间】:2017-08-25 21:17:43
【问题描述】:

期望的行为

根据所有表格的前两列中的搜索匹配显示或隐藏表格(整个表格,而不是表格单元格) - 如果在 <tr> 的第一或第二 <td> 中存在匹配,则显示表格,否则隐藏表格。

我的尝试

jsFiddle

$("input").on("keyup", function() {
  var matcher = new RegExp($(this).val(), "gi");
  $(".my_table")
    .hide()
    .filter(function() {
      return matcher.test($(this).find("td").text());
    })
    .show();
});
table {
  font-family: arial, sans-serif;
  border-collapse: collapse;
  width: 50%;
}

td,
th {
  border: 1px solid #dddddd;
  text-align: left;
  padding: 8px;
}

tr:nth-child(even) {
  background-color: #dddddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text">

<table class="my_table">
  <thead>
    <tr>
      <th>
        First Name
      </th>
      <th>Last Name</th>
      <th>Text</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>David</td>
      <td>Johnman</td>
      <td>Here is some text</td>
    </tr>
    <tr>
      <td>Felix</td>
      <td>Mann</td>
      <td>Cake</td>
    </tr>
    <tr>
      <td>Peter</td>
      <td>Pan</td>
      <td>Green green grass of home</td>
    </tr>
</table>

<br><br>

<table class="my_table">
  <thead>
    <tr>
      <th>
        First Name
      </th>
      <th>Last Name</th>
      <th>Text</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>David</td>
      <td>Stone</td>
      <td>Here is text</td>
    </tr>
    <tr>
      <td>Trevor</td>
      <td>Barry</td>
      <td>Cake</td>
    </tr>
    <tr>
      <td>Xylophone</td>
      <td>Greet</td>
      <td>Green green grass of home</td>
    </tr>
</table>

如果这有助于定位搜索,不反对将类放在每行的前两个表格单元格中,只是不完全确定如何定位正在过滤的表格实例。

最终我想在输入 3 个字符后开始过滤,因此可能会将代码包装在输入长度的条件检查中,并在输入长度为 0 时显示所有表格(在退格内容之后)。

【问题讨论】:

    标签: jquery jquery-filter


    【解决方案1】:

    只是发布一个我最终开发的解决方案,即使它与公认的答案不同(因为它朝着不同的方向发展),以防它帮助其他人采用另一种方法。它不是精简或优化的,但这可能有助于其他人看到逻辑的不同“部分”。

    它会根据搜索输入(最少 3 个字符)过滤表格并突出显示匹配的文本。它仅匹配每个 &lt;tr&gt; 的前两个 &lt;td&gt; 中的内容 - 在第一个单元格中匹配内容的开头,在第二个单元格中匹配内容中的任何位置。

    function search_tds(input_val) {
      $("table").each(function() {
        var match_counter = 0;
    
        // instance of table
        var $this = $(this);
        // first and second cells in each row
        var $tds = $this.find("td:nth-child(1),td:nth-child(2)");
    
        $tds.each(function(ind, val) {
          var cell = $tds[ind];
          var cell_text = cell.innerText;
    
          // if the first cell, perform check at start of string
          if ($(this).is(":nth-child(1)")) {
            var is_at_start_of_string =
              cell_text.toLowerCase().indexOf(input_val.toLowerCase()) === 0;
            // remove span tags to remove 'history' state
            // ie if there was existing match and then pasted in
            // another matching value
            if (is_at_start_of_string === false) {
              cell.innerHTML = cell.innerText;
            }
          } else if ($(this).is(":nth-child(2)")) {
            // if the second cell, perform check anywhere in string
            var exists_in_string =
              cell_text.toLowerCase().indexOf(input_val.toLowerCase()) !== -1;
            // remove span tags to remove 'history' state
            // ie if there was existing match and then pasted in
            // another matching value
            if (exists_in_string === false) {
              cell.innerHTML = cell.innerText;
            }
          }
    
          if (is_at_start_of_string === true || exists_in_string === true) {
            match_counter += 1;
            // cell.innerHTML = cell.innerText.replace(
            //  input_val,
            //  '<span class="matched_text">' + input_val + "</span>"
            //);
            // to replace with accurate case, see:  
            // https://stackoverflow.com/a/3294644/1063287
            var reg = new RegExp(input_val, 'i');
            cell.innerHTML = cell.innerText.replace(reg, '<span class="matched_text">$&</span>');
          }
        });
    
        if (match_counter > 0) {
          $(this).css("display", "table");
        } else {
          $(this).css("display", "none");
        }
      });
    }
    
    $(document).on("keyup", "input", function() {
      var input_val = $(this).val();
      var input_length = input_val.length;
      if (input_length > 2) {
        search_tds(input_val);
      } else if (input_length <= 2) {
        $("table").css("display", "table");
        $("span").removeClass("matched_text");
      }
    });
    table {
      font-family: arial, sans-serif;
      border-collapse: collapse;
      width: 80%;
      table-layout: fixed;
      margin-left: auto;
      margin-right: auto;
    }
    
    td,
    th {
      border: 1px solid #000;
      text-align: left;
      padding: 8px;
      width: 33.3%;
    }
    
    .matched_text {
      background: yellow;
    }
    
    input {
      padding: 10px;
      width: 80%;
      margin: 10px auto;
      display: block;
      background: #eee;
      color: #505050;
      border: 1px solid #b0b0b0;
      font-size: 20px;
    }
    
    * {
      box-sizing: border-box;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <input type="text" placeholder="enter search text (3 characters minimum)...">
    
    <table>
    
      <tbody>
        <tr>
          <td>011010</td>
          <td>best</td>
          <td>this text is not searched zest</td>
        </tr>
        <tr>
          <td>020110</td>
          <td>vest 011010</td>
          <td>this text is not searched jest</td>
        </tr>
      </tbody>
    
    </table>
    
    <br>
    
    <table>
    
      <tbody>
        <tr>
          <td>808080</td>
          <td>Jest</td>
          <td>this text is not searched best</td>
        </tr>
        <tr>
          <td>805601</td>
          <td>Pest</td>
          <td>this text is not searched chest</td>
        </tr>
      </tbody>
    
    </table>
    
    <br>
    
    <table>
    
      <tbody>
        <tr>
          <td>020101</td>
          <td>zest</td>
          <td>this text is not searched vest</td>
        </tr>
        <tr>
          <td>501025</td>
          <td>chesT</td>
          <td>this text is not searched 808080</td>
        </tr>
      </tbody>
    
    </table>

    【讨论】:

      【解决方案2】:

      您可以将搜索限制为 :first-child 和第二个孩子 (:nth-child(2)) - 一起:

      return matcher.test($(this).find("td:first-child,td:nth-child(2)").text());
      

      或者,正如您所建议的,您可以向前两个 td 添加一个类,例如searchable,并将查询字符串细化为td.searchable

      【讨论】:

      • 我试过这段代码,例如,当输入da 时,第二个表是隐藏的,而第一个表是可见的,即使两个表都包含搜索的文本 - 所以我的缺少的原始逻辑。 jsFIddle link
      • 在使用g 选项时,似乎有一个带有RegExp 对象的issue,请参阅此example。当我将g 放到你的小提琴中时,它就起作用了。
      猜你喜欢
      • 1970-01-01
      • 2012-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-19
      • 1970-01-01
      • 2023-03-22
      • 2023-01-23
      相关资源
      最近更新 更多