dogrunjp
9/6/2015 - 1:13 AM

ページャ付きインクリメンタルサーチのjQueryによる実装。

ページャ付きインクリメンタルサーチのjQueryによる実装。

ページャ付きインクリメンタルサーチをjQueryで実装する

はじめに

jQueryには、高機能なテーブル描画プラグインが色々開発されていて、Webサイトにある程度整形した形でデータをリスト表示しようとすると、インタラクション付きのプラグインを使ってしまうのが簡単だろうと思います。

最近自分が良いなと思っているテーブル描画プラグインはDynatable.jsColumnsなどで、検索やページャの機能をインタラクティブに実装したかなり作り込まれたプラグインで、データ一覧などのテーブルをjavascriptで動的に描画するようなときは大抵これで済むのでは、、と思っています。特にColumnsは、テンプレートエンジンのMustacheを利用していて、この手のプラグインでは最も自由度の高いレイアウトができそうです。

ただしColumnsでもイテレータによって生成される値がTABLEの行としてHTMLにレンダリングされた文字列で、場合によって、例えばBootstrapのコンポーネントでリスト的に表示したいようなケースでは使えなかったりします。

インクリメンタルサーチとページャのjQueryによる実装

ということで、HTML(+CSS)でレイアウトした要素をクライアント側で動的に繰り返し描画したかったら、結局自分でjavascriptを書くことになります。自分もどう処理しようか色々迷った実装なのでメモ程度にサンプルを残しておくことにします。

インクリメンタルサーチはキー入力があるたびにgetJSONを呼出し、入力された文字でフィルターするような処理で割とスムースに描画できました(データの大きさによるけど)。

ページャに関して自分で位置から作るのは怠いなぁ、という気持ちが勝りページネーションのプラグインを使うことにしました。

プラグイン(例えばjquery.getentry.jsと名前を付けてどこかにおいておく)

;(function($){
    $.fn.getentry = function(nums, q){
        var regexp = new RegExp(q, 'i');

        $.getJSON("summary.json", function(data){
            if (q != ""){
                data = data.filter(function (item, index, paging) {
                        str = item.description;
                        if (str.match(regexp)) return true;
                    });
            }

            $("#entries").empty();
            $("#pagination").empty();

            var item_nums = data.length;
            var slices = [];
            var slice_data;

            $("#pagination").paging(item_nums, {
                format: '[< ncnnn >]',
                perpage: nums,
                onSelect: function (page) {
                    slices = this.slice;
                    showItems();
                },
                onFormat: function (type) {
                    switch (type) {
                        case 'block':
                            return '<a>' + this.value + '</a>';
                        case 'next': // >
                            return '<a>&gt;</a>';
                        case 'prev': // <
                            return '<a>&lt;</a>';
                        case 'first': // [
                            return '<a>first</a>';
                        case 'last': // ]
                            return '<a>last</a>';
                    }
                }
            });

            function showItems(){
                $("#entries").empty();
                slice_data = data.slice(slices[0], slices[1]);
                $(slice_data).each(function(){
                 $('<p> + this.description + </p>').appendTo("#entries");
                });
            }
        });
    };
})(jQuery);


プラグインを呼び出すhtmlに記述するスクリプト

<script src="./js/jquery.getenrty.js"></script>
<script src="./js/jquery.paging.min.js"></script>
<script src="./js/jquery.easy-paging.js"></script>
<script type="text/javascript">
    $(function () {
        var line_number = 5;
        var query_text = "";
        $(document).getentry(line_number, query_text);

        $("#line_num li").on('click', function () {
            new_line_number = $(this).text();
            if (line_number != new_line_number) {
                line_number = new_line_number;
                $(document).getentry(line_number, query_text);
            }
        });
        $("input:text").on("keypress keyup change", function (e) {
            query_text =$("input:text").val();
            if (e.keyCode == 46 || e.keyCode == 8) {
                if (query_text == "") {
                    $(document).getentry(line_number, query_text);
                } else {
                    $(document).getentry(line_number, query_text);
                }
            }else if (e.keyCode == 13) {
                //何もしない
            }else if(query_text  != ""){
                $(document).getentry(line_number, query_text);
            }
        });


    })
</script>

上のスクリプトでは、テキストの入力フォームの他にBootstrapのdropdown-menuを利用して表示するサンプル数を設定することを想定しています。dropdown-menuの値が変わると検索文字を入力した時と同様にプラグインを読み込みデータを再レンダリングします。

※データとページャを描画する空要素も呼び出す側のHTMLのどこかにおいておく

<div id="entries"></div>
<div id="pagination"></div>