Cách thực hiện tìm kiếm và lọc theo thời gian thực trên bảng HTML


139

Tôi đã Googling và tìm kiếm Stack Overflow một thời gian, nhưng tôi không thể khắc phục được vấn đề này.

Tôi có một bảng HTML tiêu chuẩn, chứa, nói, trái cây. Thích như vậy:

<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>

Ở trên này tôi có một hộp văn bản, mà tôi muốn tìm kiếm bảng dưới dạng người dùng. Vì vậy, nếu họ gõ Grechẳng hạn, hàng màu cam của bảng sẽ biến mất, để lại Apple và Nho. Nếu họ tiếp tục và gõ Green Grhàng Apple sẽ biến mất, chỉ để lại nho. Tôi hy vọng điều này là rõ ràng.

Và, nếu người dùng xóa một số hoặc tất cả truy vấn của họ khỏi hộp văn bản, tôi nên thích tất cả các hàng khớp với truy vấn để xuất hiện lại.

Trong khi tôi biết cách loại bỏ một hàng trong jQuery, tôi có ít ý tưởng về cách thực hiện tìm kiếm và loại bỏ các hàng một cách có chọn lọc dựa trên điều này. Có một giải pháp đơn giản cho việc này? Hay một plugin?

Nếu bất cứ ai có thể chỉ cho tôi đi đúng hướng, nó sẽ rất tuyệt vời.

Cảm ơn bạn.


Câu trả lời:


307

Tôi đã tạo ra những ví dụ này.

Tìm kiếm indexOf đơn giản

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();
});

Bản trình diễn : http://jsfiddle.net/7BUmG/2/

Tìm kiếm biểu thức chính quy

Chức năng nâng cao hơn bằng cách sử dụng các biểu thức thông thường sẽ cho phép bạn tìm kiếm các từ theo bất kỳ thứ tự nào trong hàng. Nó sẽ hoạt động tương tự nếu bạn gõ apple greenhoặc 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();
});

Bản trình diễn : http://jsfiddle.net/dfsq/7BUmG/1133/

Ra mắt

Khi bạn thực hiện lọc bảng với tìm kiếm trên nhiều hàng và cột, điều rất quan trọng là bạn phải xem xét hiệu suất và tốc độ tìm kiếm / tối ưu hóa. Nói đơn giản là bạn không nên chạy chức năng tìm kiếm trên mỗi lần nhấn phím, điều đó là không cần thiết. Để ngăn quá trình lọc chạy quá thường xuyên, bạn nên gỡ bỏ nó. Ví dụ mã trên sẽ trở thành:

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

Bạn có thể chọn bất kỳ triển khai gỡ lỗi nào , ví dụ như từ Lodash _.debounce hoặc bạn có thể sử dụng một cái gì đó rất đơn giản như tôi sử dụng trong các bản demo tiếp theo (gỡ lỗi từ đây ): http://jsfiddle.net/7BUmG/6230/http: / /jsfiddle.net/7BUmG/6231/ .


3
Tôi khá xanh với công cụ này, nhưng nếu tôi muốn kết hợp này thành bàn của tôi, tôi chỉ cần thay đổi #tablevào idcác bảng của tôi? Có cần phải có thay đổi bổ sung để làm việc với <thead><tbody>thẻ không? Tôi đã bao gồm tập lệnh và html từ liên kết jsfiddle, thay đổi #id, nhưng tôi không lọc được.
JoshP

10
@JoshP Sctipt hoạt động với tất cả các hàng. Nếu bạn muốn chỉ lọc những người bên trong, <tbody>bạn nên đổi thành var $rows = $('#id-of-your-table tbody tr');.
dfsq

2
@JoshP Không, không có gì ngoài jQuery là bắt buộc. Chỉ cần đảm bảo rằng bạn chạy mã của mình trong DOMReady hoặc sau khi HTML được tải.
dfsq

2
Tôi khuyên bạn nên tăng cường cách tiếp cận này vì nó khá tốn tài nguyên. Đặt tất cả các chuỗi được tinh chỉnh vào một mảng các đối tượng có hai trường: tham chiếu đến <tr>DOMEuity và chuỗi. Bằng cách này, khi keyup()bạn tìm kiếm các chuỗi đó (nhanh hơn nhiều) và có các hàng tương ứng sẵn sàng để được thao tác. Đó là thủ tục thiết lập tốn kém đầu tiên sau đó nên được thực hiện ngay sau khi tải. Tất cả những thay đổi này chỉ là sửa chữa nhỏ, phần trung tâm thực tế vẫn còn như thể hiện trong câu trả lời này. Cách tiếp cận này cũng có thể và khá dễ thực hiện với jQuery.
pid

2
@confuseMind Sử dụng $('#table tr:not(:first)')bộ chọn.
dfsq

10

tôi có một plugin jquery cho việc này. Nó cũng sử dụng jquery-ui. Bạn có thể xem một ví dụ ở đây 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
        });

8

Đây là giải pháp tốt nhất để tìm kiếm bên trong bảng HTML trong khi bao trùm tất cả các bảng , (tất cả td, tr trong bảng), javascript thuần túy và càng ngắn càng tốt:

<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>

3
Để bảo vệ hàng tiêu đề bảng không biến mất, hãy thêm id vào hàng như: <tr id = 'tableHeader'> và thay đổi câu lệnh khác cuối cùng thành: if (tr [i] .id! = 'TableHeader') {tr [i ] .style.display = "none";} Nó không được đề cập trong câu hỏi nhưng tôi muốn nó bao gồm điều đó để làm cho nó toàn diện.
Tarik

Thay vì so sánh id bằng cách sử dụng! =, Tôi khuyên bạn nên thay đổi cái cuối cùng thành cái này:} other if (! Tr [i] .id.match ('^ tableHeader')) {Điều này cho phép một người có nhiều hơn một bảng, mỗi bảng với tiêu đề riêng của họ. Cần nhiều công việc hơn để tham số hóa hàm searchTable bằng cách chuyển vào id bảng.
Tom Ekberg

3

Cảm ơn bạn @dfsq vì mã rất hữu ích!

Tôi đã thực hiện một số điều chỉnh và có thể một số người khác cũng thích chúng. Tôi đảm bảo rằng bạn có thể tìm kiếm nhiều từ mà không cần phải khớp một cách nghiêm ngặt.

Hàng ví dụ:

  • Táo và lê
  • Táo và Chuối
  • Táo và cam
  • ...

Bạn có thể tìm kiếm 'ap pe' và nó sẽ nhận ra hàng đầu tiên
Bạn có thể tìm kiếm 'chuối táo' và nó sẽ nhận ra hàng thứ hai

Bản trình diễn: http://jsfiddle.net/JeroenSormani/xhpkfwgd/1/

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

  $rows.hide().filter(function() {
    var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
    var matchesSearch = true;
    $(val).each(function(index, value) {
      matchesSearch = (!matchesSearch) ? false : ~text.indexOf(value);
    });
    return matchesSearch;
  }).show();
});

Tìm kiếm chắc chắn - Tôi đã phải sửa đổi nó một chút để ngăn các tiêu đề và chân trang của Bảng biến mất, bằng cách thay đổi: var $rows = $('#WorldPlayersTable tr'); thành - var $rows = $('#WorldPlayersTable tbody tr');
Drefetr

2

Tôi thấy câu trả lời của dfsq rất hữu ích. Tôi đã thực hiện một số sửa đổi nhỏ áp dụng cho tôi (và tôi sẽ đăng nó ở đây, trong trường hợp nó có ích cho người khác).

  1. Sử dụng classnhư các hook, thay vì các phần tử bảngtr
  2. Tìm kiếm / so sánh văn bản trong một đứa trẻ classtrong khi hiển thị / ẩn cha mẹ
  3. Làm cho nó hiệu quả hơn bằng cách lưu trữ các $rowsthành phần văn bản vào một mảng chỉ một lần (và tránh $rows.lengthtính toán thời gian)

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

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

$('#search').keyup(function() {
  var val = $.trim($(this).val()).replace(/ +/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>


2

Giải pháp Javascript thuần túy:

Hoạt động cho TẤT CẢ các cột và Không phân biệt chữ hoa chữ thường:

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";
        }
      } 
    }
  }
}

1

bạn có thể sử dụng javascript như thế này

<script>
function myFunction() {
  var input, filter, table, tr, td, i;
  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")[0];
    if (td) {
      if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }       
  }
}
</script>



-1

Nếu bạn có thể tách html và dữ liệu, bạn có thể sử dụng các thư viện bên ngoài như datatables hoặc cái tôi đã tạo. https://github.com/thehitechpanky/js-bootstrap-tables

Thư viện này sử dụng chức năng keyup để tải lại tabledata và do đó nó dường như hoạt động như tìm kiếm.

function _addTableDataRows(paramObjectTDR) {
    let { filterNode, limitNode, bodyNode, countNode, paramObject } = paramObjectTDR;
    let { dataRows, functionArray } = paramObject;
    _clearNode(bodyNode);
    if (typeof dataRows === `string`) {
        bodyNode.insertAdjacentHTML(`beforeend`, dataRows);
    } else {
        let filterTerm;
        if (filterNode) {
            filterTerm = filterNode.value.toLowerCase();
        }
        let serialNumber = 0;
        let limitNumber = 0;
        let rowNode;
        dataRows.forEach(currentRow => {
            if (!filterNode || _filterData(filterTerm, currentRow)) {
                serialNumber++;
                if (!limitNode || limitNode.value === `all` || limitNode.value >= serialNumber) {
                    limitNumber++;
                    rowNode = _getNode(`tr`);
                    bodyNode.appendChild(rowNode);
                    _addData(rowNode, serialNumber, currentRow, `td`);
                }
            }
        });
        _clearNode(countNode);
        countNode.insertAdjacentText(`beforeend`, `Showing 1 to ${limitNumber} of ${serialNumber} entries`);
    }
    if (functionArray) {
        functionArray.forEach(currentObject => {
            let { className, eventName, functionName } = currentObject;
            _attachFunctionToClassNodes(className, eventName, functionName);
        });
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.