SlickGridで行をフィルタリングするサンプル

[SlickGridのコンテキストメニューで行の追加と削除のサンプル](http://qiita.com/items/c4bb90a1bcf9cc071c32/edit)の続きです。

# フィルタリングのサンプル

本家では[mleibman.github.io/SlickGrid/examples/example-header-row.html](http://mleibman.github.io/SlickGrid/examples/example-header-row.html)にフィルタリングのサンプルがあります。

私が書いたフィルタリングのサンプルは
http://hnakamur.github.io/slickgrid_example/
にあります（ソースは https://github.com/hnakamur/slickgrid_example/ ）

# フィルタのテキスト入力欄の作成方法

グリッドの ```showHeaderRow``` オプションを指定すると列ヘッダー行の下にスクロール固定の行が1行追加されます。これのことをheaderRowと呼んでいます（列ヘッダーと紛らわしいですが）。 ```headerRowHeight``` オプションでその行の高さを指定します。

通常の行の高さは[Grid Options · mleibman/SlickGrid Wiki](https://github.com/mleibman/SlickGrid/wiki/Grid-Options)の ```headerRowHeight```オプションのデフォルト値で25pxとなっています。

ここでは、フィルタ用にテキストフィールドを入れるので ```headerRowHeight``` はそれより大きめの30pxを指定しています。

```js:js/example.js
  var options = {
    editable: true,
    autoEdit: false,
    multiColumnSort: true,
    showHeaderRow: true,
    headerRowHeight: 30,
    explicitInitialization: true
  };
```

headerRow の中身にテキストフィールドを作るためには上記のように ```explicitInitialization``` オプションをtrueにする必要があります。

そして、```grid.onHeaderRowCellRendered``` にテキストフィールドを作る処理を記述します。その後、```grid.init()```を呼び出します。

```js:js/example.js
  grid.onHeaderRowCellRendered.subscribe(function (e, args) {
    if (args.column.id === "id") return;
    var cell = $(args.node);
    cell.empty();
    $(document.createElement("input"))
      .attr("type", "text")
      .data("columnId", args.column.id)
      .val(columnFilters[args.column.id])
      .appendTo(cell);
  });

  grid.init();
```

# データをフィルタリングする処理の実装

フィルタリングの実装は以下のようにします。ここではテキストフィールドに入力した値が部分一致していたらマッチとし、そうでない行は除外するようにしています。

```js:js/example.js
  var columnFilters = {};
  function filter(item) {
    for (var columnId in columnFilters) {
      if (columnId !== undefined && columnFilters[columnId] !== "") {
        var c = grid.getColumns()[grid.getColumnIndex(columnId)];
        var val = item[c.field];
        if (val === undefined || val.indexOf(columnFilters[columnId]) === -1) {
          return false;
        }
      }
    }
    return true;
  }
```

# フィルタリングのイベントハンドラの設定

フィルタリングのイベントハンドラを設定する処理は本家の例では以下のようなコードで、キーを押すたびにフィルタリングするようになっています。

```js
  $(grid.getHeaderRow()).delegate(":input", "change keyup", function (e) {
    var columnId = $(this).data("columnId");
    if (columnId != null) {
      columnFilters[columnId] = $.trim($(this).val());
      dataView.refresh();
    }
  });
```

最後に、フィルタをDataViewに適用するために```setFilter```を呼びます。

```js:js/example.js
  dataView.setFilter(filter);
```

## jquery.japanese-input-changeプラグインを使った改良版

本家の例の実装だと、日本語の場合はIMEで変換中にもkeyupイベントが発火して、変換中の文字列でフィルタリングが実行され1件もヒットせずに全ての行が非表示になってしまうので使い勝手が悪いです。

冒頭に上げた私が書いたフィルタリングのサンプルではjquery.japanese-input-changeプラグインを使って、IMEで未確定な場合とキー入力が続いている場合はフィルタリングを実行しないようにしています。IME確定済みでキー入力が落ち着いてから0.5秒後にフィルタリングが実行されます。

フィルタリングのイベントハンドラは以下のようにして設定します。jQueryのライブイベントを使うように指定しているので、grid.init()の前で実行しても問題ありません。

```js:https://github.com/hnakamur/slickgrid_example/blob/658a8c8d717442690b07c3d102ff792f0d7b9738/js/example.js#L312-L322
  function updateFilters() {
    var columnId = $(this).data("columnId");
    if (columnId != null) {
      columnFilters[columnId] = $.trim($(this).val());
      dataView.refresh();
    }
  }
  $(grid.getHeaderRow()).japaneseInputChange('input[type=text]', 500,
      updateFilters);

  grid.init();
```

jquery.japanese-input-changeプラグインについては、[日本語入力環境でキー入力が一段落したらハンドラを実行するjQueryプラグインを作ってみた - Qiita](http://qiita.com/hnakamur/items/9a9ca2663285e19088c7)をご参照ください。