HTMLテーブルでリアルタイム検索とフィルターを実行する方法


139

私はしばらくの間、スタックオーバーフローをグーグル検索して検索してきましたが、この問題を回避することはできません。

たとえば、フルーツを含む標準の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すると、リンゴの列は消え、ブドウだけが残るはずです。これが明確であることを願っています。

また、ユーザーがクエリの一部またはすべてをテキストボックスから削除した場合、クエリに一致するすべての行が再び表示されるようにする必要があります。

jQueryでテーブル行を削除する方法は知っていますが、これに基づいて検索を実行し、行を選択的に削除する方法についてはほとんど考えていません。これに対する簡単な解決策はありますか?またはプラグイン?

誰かが私を正しい方向に向けることができればそれは素晴らしいでしょう。

ありがとうございました。


回答:


307

これらの例を作成しました。

単純な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 greengreen 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/


3
私はこのようなものとはかなり緑んだけど、私は私のテーブルにこれを組み込みたい場合は、私は変更する必要はない#tableid私のテーブルの?<thead>および<tbody>タグを使用するには、追加の変更が必要ですか?jsfiddleリンクからのスクリプトとhtmlを含めて、を変更しましたが#id、フィルタリングされません。
JoshP 2013年

10
@JoshP Sctiptはすべての行で機能します。内部のフィルターのみをフィルター処理する<tbody>場合は、に変更する必要がありますvar $rows = $('#id-of-your-table tbody tr');
dfsq 2013年

2
@JoshPいいえ、jQuery以外は必要ありません。DOMReadyで、またはHTMLが読み込まれた後にコードを実行するようにしてください。
dfsq 2013年

2
これはかなりのリソースを消費するため、このアプローチを強化することをお勧めします。洗練されたすべての文字列を、<tr>DOMElementと文字列への参照という2つのフィールドを持つオブジェクトの配列に入れます。このようにして、keyup()これらの文字列を検索すると(これは非常に高速です)、対応する行を操作できるようになります。この最初のコストのかかるセットアップ手順は、ロード直後に一度だけ実行する必要があります。これらの変更はすべて小さな修正であり、実際の中心部分はこの回答に示されているように残っています。このアプローチも可能であり、jQueryなしで実装するのはかなり簡単です。
pid

2
@confusedMind $('#table tr:not(:first)')セレクタを使用します。
dfsq 2015年

10

このための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
        });

8

すべてのテーブルテーブル内のすべてのtd、tr)、純粋なJavaScript、および可能な限り短いものをカバーながら、HTMLテーブル内を検索するための最良のソリューションを次に示します。

<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
テーブルヘッダー行が消えないように保護するには、<tr id = 'tableHeader'>のように行にidを追加し、最後のelseステートメントを次のように変更します:if(tr [i] .id!= 'tableHeader'){tr [i ] .style.display = "none";}質問には記載されていませんが、包括的にするためにそれをカバーしたかったのです。
Tarik、2016年

!=を使用してIDを比較する代わりに、最後のelseを次のように変更することをお勧めします:} else if(!tr [i] .id.match( '^ tableHeader')){これにより、それぞれが複数のテーブルを持つことができます独自のヘッダー付き。テーブルIDを渡してsearchTable関数をパラメーター化するには、さらに作業が必要です。
Tom Ekberg、2018年

3

非常に役立つコードをありがとう@dfsq!

私はいくつかの調整を行い、おそらく他の人もそれらを気に入っています。厳密に一致することなく、複数の単語を検索できるようにしました。

行の例:

  • リンゴとナシ
  • リンゴとバナナ
  • リンゴとオレンジ
  • ...

「ap pe」を検索すると、最初の行が認識さ
れます「banana apple」を検索すると、2番目の行が認識されます

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

: -ソリッド検索私は変更することで、消えてからの私のテーブルのヘッダー&フッターを防ぐために、わずかにそれを変更しなければならなかった var $rows = $('#WorldPlayersTable tr'); -に var $rows = $('#WorldPlayersTable tbody tr');
Drefetr

2

私はdfsqの回答のコメントが非常に役立つと感じました。私は自分に適用できるいくつかのマイナーな変更を加えました(他の人に役立つ場合に備えて、ここに投稿します)。

  1. classテーブル要素の代わりにフックとして使用tr
  2. class親を表示/非表示にしているときに子内のテキストを検索/比較する
  3. $rowsテキスト要素を1回だけ配列に格納することで(および$rows.length時間の計算を回避して)より効率的にする

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

純粋な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";
        }
      } 
    }
  }
}

1

あなたはこのようなネイティブのJavaScriptを使うことができます

<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

htmlとデータを分離できる場合は、データテーブルや私が作成したライブラリなどの外部ライブラリを使用できます。https://github.com/thehitechpanky/js-bootstrap-tables

このライブラリは、キーアップ関数を使用してテーブルデータをリロードするため、検索のように機能するように見えます。

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);
        });
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.