List.jsの使い方

List.jsなるJavascriptライブラリがスゴイ!みたいな記事を見て、ちょっと感動し使ってみることにした。

しかし公式の説明を読んでもピンと来ない。
なぜなら私はhtmlやcssを書くことはできるが、しっかり理解できていなかったからだった。
そんな私がいきなりJqueryを使ったList.jsなど頭に入ってくるわけがない。

ということで、取り敢えず「Javascript 入門」と「Jquery」と「CSS 入門」をググり、なんとなく掴んでから再度List.jsへ挑んだ。
JavascriptCSSJqueryについてはSlideShareなどでまとめている人がいて、かなり理解しやすかった。

ここでは、そんな入門者がList.jsについて理解できるようにList.jsの使い方を書いていく。

今回紹介するList.jsを使ったリスト操作

  1. ソート
  2. 検索
  3. フィルタ
  4. 追加
  5. 編集
  6. 削除

ここで紹介した例は、githubで公開したので、全体をみたい場合はそちらを参照されたし。
clashm45/listjs_example · GitHub

  1. ソート

List.js公式サイトのExamples - Basic Exapmle にある。
http://listjs.com/examples/standard.html

ポチッと押すとリストがソートされて、素晴らしい!
しかも、ソートするだけならかなり簡単に実装できてしまう。
HTML

    <div id="hacker-list">
        <table border="1">
            <tr>
                <td class="sort" data-sort="name">Sort by name</td>
                <td class="sort" data-sort="city">Sort by city</td>
            </tr>
        </table>

        <ul class="list">
            <li>
                <h3 class="name">Jonny</h3>
                <p class="city">Stockholm</p>
            </li>
            <li>
                <h3 class="name">Jonas</h3>
                <p class="city">Berlin</p>
            </li>
            ~~~~
        </ul>
    </div>

Javascript

    <script type="text/javascript">
        var options = {
          valueNames : [ 'name', 'city' ]
        };
        var hackerList = new List('hacker-list', options);
    </script>

注意する点は、"hacker-list"がid属性でないとダメなこと。

  1. 検索

検索もかなり簡単にできる。結構感動モノ。
HTML

    <div id="hacker-list">
        <table border="1">
            <tr>
                <td class="sort" data-sort="name">Sort by name</td>
                <td class="sort" data-sort="city">Sort by city</td>
                <td><input type="text" class="search"></td>
            </tr>
        </table>
        ~~~~

Javascript
なんとJavascriptはソートの時と同じでOK!!

"search"ってクラスの入力をつけるだけで、hacker-listに定義されている項目"name", "city"から検索してくれる。

  1. フィルタ

フィルタってのはあるカテゴリのデータだけを表示したりするときに使用する。
ここからJqueryとかを使いながら、リストを操作する必要がある。

HTML

    <div id="hacker-list">
        <table border="1">
            <tr>
                <td class="sort" data-sort="name">Sort by name</td>
                <td class="sort" data-sort="city">Sort by city</td>
                <th />
            </tr>
            <tr>
                <td id="filter-none">Show all</td>
                <td id="filter-java">Only show Java user</td>
                <td id="filter-cplus">Only show C++ user</td>
            </tr>
        </table>

        <table>
            <thead>
                <tr>
                    <th>use</th>
                    <th>name</th>
                    <th>city</th>
                </tr>
            </thead>
            <tbody class="list">
                <tr>
                    <td class="use">Java</td>
                    <td class="name">Jonny</td>
                    <td class="city">Stockholm</td>
                </tr>
                <tr>
                    <td class="use">C++</td>
                    <td class="name">Jonas</td>
                    <td class="city">Berlin</td>
                </tr>
                <tr>
                    <td class="use">C++</td>
                    <td class="name">Amazing</td>
                    <td class="city">London</td>
                </tr>
                <tr>
                    <td class="use">Java</td>
                    <td class="name">Excellent</td>
                    <td class="city">Paris</td>
                </tr>
            </tbody>
        </table>
    </div>

Javascript

    <script type="text/javascript">
        var options = {
            valueNames : [ 'use', 'name', 'city' ]
        };
        var hackerList = new List('hacker-list', options);

        $('#filter-java').click(function() {
            hackerList.filter(function(item) {
                if (item.values().use == "Java") {
                    return true;
                } else {
                    return false;
                }
            });
            return false;
        });

        $('#filter-cplus').click(function() {
            hackerList.filter(function(item) {
                if (item.values().use == "C++") {
                    return true;
                } else {
                    return false;
                }
            });
            return false;
        });
        $('#filter-none').click(function() {
            hackerList.filter();
            return false;
        });

    </script>

よーく読むと理解できると思うが、"filter-java"とか"filter-cplus"をクリックした時のfunctionを記述している。
そして、hackerList.filterへさらに表示(true)|非表示(false)を返すfunctionを渡している。

  1. 追加

テーブル形式のリストへ行を追加する。
結構javascriptを書くことになるが、List.jsやJqueryが無かった頃に比べると格段に書きやすくなっている。
HTML

    <div id="hacker-list">
        <table border="1">
            <thead>
                <tr>
                    <th>use</th>
                    <th>name</th>
                    <th>city</th>
                </tr>
            </thead>
            <tbody class="list">
                <tr>
                    <td class="use">Java</td>
                    <td class="name">Jonny</td>
                    <td class="city">Stockholm</td>
                </tr>
                <tr>
                    <td class="use">C++</td>
                    <td class="name">Jonas</td>
                    <td class="city">Berlin</td>
                </tr>
                <tr>
                    <td class="use">C++</td>
                    <td class="name">Amazing</td>
                    <td class="city">London</td>
                </tr>
                <tr>
                    <td class="use">Java</td>
                    <td class="name">Excellent</td>
                    <td class="city">Paris</td>
                </tr>
            </tbody>
        </table>

        <table>
            <tr>
                <td><input type="text" id="use-field" placeholder="use" /></td>
                <td><input type="text" id="name-field" placeholder="name" /></td>
                <td><input type="text" id="city-field" placeholder="city" /></td>
                <td><button id="add-btn">Add</button></td>
            </tr>
        </table>
    </div>

Javascript

    <script type="text/javascript">
        var options = {
            valueNames : [ 'use', 'name', 'city' ]
        };
        var hackerList = new List('hacker-list', options);

        var useField = $('#use-field'),
            nameField = $('#name-field'),
            cityField = $('#city-field'),
            addBtn = $('#add-btn');

        addBtn.click(function() {
            hackerList.add({
                use  : useField.val(),
                name : nameField.val(),
                city : cityField.val()
            });
            clearFields();
        });

        function clearFields() {
            useField.val('');
            nameField.val('');
            cityField.val('');
        }
    </script>

この例では、追加用の入力フィールドを用意して、そこに入力した値をAddボタン押したら追加される。
しっっっっっかり読むと理解できるはずだが、ここでもaddBtnへclick時のfunctionを書いている。
List.jsのListクラスにあるメソッド#addを使って、連想配列?を挿入している。

  1. 編集

既にあるリストの項目を変更したい時に使う。
HTML

            <tbody class="list">
                <tr>
                    <td class="id" style="display: none;">1</td>
                    <td class="use">Java</td>
                    <td class="name">Jonny</td>
                    <td class="city">Stockholm</td>
                    <td><button class="edit-item-btn">Edit</button></td>
                </tr>

Javascript

    <script type="text/javascript">
        var options = {
            valueNames : [ 'id', 'use', 'name', 'city' ]
        };
        var hackerList = new List('hacker-list', options);

        var idField = $('#id-field')
            useField = $('#use-field'),
            nameField = $('#name-field'),
            cityField = $('#city-field'),
            addBtn = $('#add-btn'),
            editBtn = $('#edit-btn').hide(),
            editBtns = $('.edit-item-btn');

        refreshCallbacks();

        addBtn.click(function() {
            hackerList.add({
                id   : Math.floor(Math.random()*110000),
                use  : useField.val(),
                name : nameField.val(),
                city : cityField.val()
            });
            clearFields();
            refreshCallbacks();
        });

        editBtn.click(function() {
            var item = hackerList.get('id', idField.val());
            item.values({
                id : idField.val(),
                use  : useField.val(),
                name : nameField.val(),
                city : cityField.val()
            });
            clearFields();
            editBtn.hide();
            addBtn.show();
        });

        function refreshCallbacks() {
        // Needed to add new buttons to jQuery-extended object
            editBtns = $(editBtns.selector);

            editBtns.click(function() {
                var itemId = $(this).closest('tr').find('.id').text();
                var itemValues = hackerList.get('id', itemId).values();
                idField.val(itemValues.id);
                useField.val(itemValues.use);
                nameField.val(itemValues.name);
                cityField.val(itemValues.city);

                editBtn.show();
                addBtn.hide();
            });
        }

        function clearFields() {
            idField.val('');
            useField.val('');
            nameField.val('');
            cityField.val('');
        }
    </script>

まず、HTMLには各行のEditボタンと、Addボタンと同じ所へ確定用のEditボタンの追加。
しかしHTMLはそんなに変化ないが、Javascript部が大幅に難しくなったように感じるだろう。
だが焦らないで欲しい。半分は今まで見てきたものと同じだ。
実際に追加されたのは、以下だ。

  • 各行にあるEditボタンへのfunction
  • 確定用Editボタンのfunction
  • refreshCallbacks()というAddした時に追加された行のEditボタンのために再度functionを設定するfunction
  • AddボタンとEditボタンのちょっとした表示・非表示操作
  1. 削除

既にあるリストの項目を削除したい時に使う。
HTML

      <tbody class="list">
        <tr>
          <td class="id" style="display: none;">1</td>
          <td class="use">Java</td>
          <td class="name">Jonny</td>
          <td class="city">Stockholm</td>
          <td><button class="edit-item-btn">Edit</button></td>
          <td><button class="remove-item-btn">Remove</button></td>
        </tr>||<
<span class="deco" style="font-weight:bold;font-style:italic;">Javascript</span>
>|html|
  <script type="text/javascript">
      var options = {
        valueNames : [ 'id', 'use', 'name', 'city' ]
      };
      var hackerList = new List('hacker-list', options);

      var idField = $('#id-field')
      useField = $('#use-field'), nameField = $('#name-field'),
          cityField = $('#city-field'), addBtn = $('#add-btn'),
          editBtn = $('#edit-btn').hide(),
          editBtns = $('.edit-item-btn'), clearBtn = $('#clear-btn'),
          removeBtns = $('.remove-item-btn');

      refreshCallbacks();

      addBtn.click(function() {
        hackerList.add({
          id : Math.floor(Math.random() * 110000),
          use : useField.val(),
          name : nameField.val(),
          city : cityField.val()
        });
        clearFields();
        refreshCallbacks();
      });

      editBtn.click(function() {
        var item = hackerList.get('id', idField.val());
        item.values({
          id : idField.val(),
          use : useField.val(),
          name : nameField.val(),
          city : cityField.val()
        });
        clearFields();
        editBtn.hide();
        addBtn.show();
      });

      clearBtn.click(function() {
        clearFields();
        editBtn.hide();
        addBtn.show();
      })

      function refreshCallbacks() {
        // Needed to add new buttons to jQuery-extended object
        editBtns = $(editBtns.selector);
        removeBtns = $(removeBtns.selector);

        editBtns.click(function() {
          var itemId = $(this).closest('tr').find('.id').text();
          var itemValues = hackerList.get('id', itemId).values();
          idField.val(itemValues.id);
          useField.val(itemValues.use);
          nameField.val(itemValues.name);
          cityField.val(itemValues.city);

          editBtn.show();
          addBtn.hide();
        });

        removeBtns.click(function() {
          var itemId = $(this).closest('tr').find('.id').text();
          hackerList.remove('id', itemId);
        });
      }

      function clearFields() {
        idField.val('');
        useField.val('');
        nameField.val('');
        cityField.val('');
      }
    </script>

削除もremoveってボタンを追加して、それにListを操作するfunctionを記述しただけ。

全てのList操作に共通して、List.jsで追加されたListってクラスのメソッドを使って、
リストの項目を操作することでターブル・リストも操作できるって感じ。


List.jsの説明はこんな感じです。
もっと複雑なことがしたかったら、List.jsの公式リファレンスを読んで、どんなメソッドがあるのかとか調べてみてください。
# コメント頂ければ私もやってみますけど。


今後はList.jsで操作したリストを他のフレームワークでちゃんと実行できるかとかやってみようと思う。
例えば、ソートしたリストを変更して、Struts経由でDBコミットしてみたり。

以上でした。