List.jsでカンマ混じりの数値をソートする方法
List.jsでカンマ混じりの数値をソートする方法:
事の発端
https://github.com/javve/list.js/issues/623
List.jsを普通に使った場合、ソートしてもちゃんと並ばないじゃん、というやつですね。よくある問題です。表示用の文字とソート用の値を使いわけないとですね。
解決する方法は2つあります。手っ取り早く済ませる方法と、ちゃんとソート関数作る方法。
簡単に済ませる方法は、ソート用の値をちゃんと作ることです。目立たないですけど本家にサンプルもあります。
http://listjs.com/docs/
Example 6: Using data attributes and other custom attributes (introduced in v1.2.0)
以下の例では、id_percのTDにdata-perc属性を追加しました。data属性に追加する値は、ソートしやすいように桁合わせ、0埋め、小数点処理、不要な文字の削除($マーク、¥マーク、カンマ)などを事前に済ませておいてください。当然ですが、HTMLを出力する側のプログラムの修正が必要ですね。
さらに、scriptでList.jsのインスタンスを作るときに、id_percに対して一工夫します。
いつもはvalueNamesの配列にカラム名だけを渡していますが、これは、<td></td>や<span></span>なとのタグで挟まれたテキストノードの値をソートに使います。
これで、小数も%もキレイに並ぶと思います。
List.jsのsortfunctionの仕組みを使って、複数カラムのソートを実現する で調べましたが、List.jsのインスタンスはsort用の関数を持てるようになっていて、デフォルトでは
ソートする関数で解決するので、HTMLの中にソート用の値と表示用の値のデータを持たなくて済みます。
変更点は、
ソートしやすいような値をHTMLに仕込むほうがいいか、ソート関数が呼ばれるたびに文字列変換して並び替えるのがいいのかは、各自判断ください。
ソート指定したカラムの値が同じときに、パーセントの降順で並ぶサンプルを作りました。参考にどうぞ。
https://github.com/kanaxx/listjs_sample/blob/master/numbersort.html
事の発端
https://github.com/javve/list.js/issues/623
問題点
List.jsを普通に使った場合、ソートしてもちゃんと並ばないじゃん、というやつですね。よくある問題です。表示用の文字とソート用の値を使いわけないとですね。
解決策
解決する方法は2つあります。手っ取り早く済ませる方法と、ちゃんとソート関数作る方法。
解決策1 data-xxxを使って、ソート用の値を埋め込む
簡単に済ませる方法は、ソート用の値をちゃんと作ることです。目立たないですけど本家にサンプルもあります。http://listjs.com/docs/
Example 6: Using data attributes and other custom attributes (introduced in v1.2.0)
以下の例では、id_percのTDにdata-perc属性を追加しました。data属性に追加する値は、ソートしやすいように桁合わせ、0埋め、小数点処理、不要な文字の削除($マーク、¥マーク、カンマ)などを事前に済ませておいてください。当然ですが、HTMLを出力する側のプログラムの修正が必要ですね。
<table id="tableid" class="table-list" data-currentpage="1"> <thead> <tr> <th><button type="button" class="sort" data-sort="id_name">Parish Name <i class="caret"></i></button></th> <th style="width: 140px;"><button type="button" class="sort" data-sort="id_town">Town <i class="caret"></i></button></th> <th style="width: 80px;"><button type="button" class="sort" data-sort="id_give">Givers <i class="caret"></i></button></th> <th style="width: 120px;"><button type="button" class="sort" data-sort="id_comm">Commitment <i class="caret"></i></button></th> <th style="width: 120px;"><button type="button" class="sort" data-sort="id_paid">Paid to Date <i class="caret"></i></button></th> <th style="width: 120px;"><button type="button" class="sort" data-sort="id_goal">Goal <i class="caret"></i></button></th> <th style="width: 100px;"><button type="button" class="sort" data-sort="id_perc">Percent <i class="caret"></i></button></th> </tr> </thead> <tbody class="list"> <tr> <td class='id_name'>002, Blessed Sacrament </td> <td class='id_town'>Rochester </td> <td class='id_give'>107</td> <td class='id_comm'>$35,862.00</td> <td class='id_paid'>$34,904.00</td> <td class='id_goal'>$73,822.00</td> <td class='id_perc' data-perc='0.4858'>48.58%</td> <!--★ここ--> </tr>
いつもはvalueNamesの配列にカラム名だけを渡していますが、これは、<td></td>や<span></span>なとのタグで挟まれたテキストノードの値をソートに使います。
{}
を使ってname
とattr
の2つの情報を渡します。これをやることで、id_percでソートするときは、data-percの値を使うのね、ということが伝わります。<a>タグのhrefや<img>タグのsrcで並び替えたいときも、この方法を使います。<script> var options = { valueNames: [ 'id_name', 'id_town', 'id_give', 'id_comm', 'id_paid', 'id_goal', //'id_perc' { name: 'id_perc', attr: 'data-perc' }, ] }; var tableList = new List('tableID', options); </script>
解決策2 sortする関数を再定義する
List.jsのsortfunctionの仕組みを使って、複数カラムのソートを実現する で調べましたが、List.jsのインスタンスはsort用の関数を持てるようになっていて、デフォルトではnaturalSort
という関数が仕込まれています。これをハックしてやります。ソートする関数で解決するので、HTMLの中にソート用の値と表示用の値のデータを持たなくて済みます。
変更点は、
- sortイベントで呼び出される関数を別のものを指定(my_sort)を指定してインスタンス作成をし、
- my_sortではカラム名を見分けて呼び出す関数を変えるようにし、
- my_numbersort関数は、要らない文字列を削り、小数に変換してソートする
<script> var options = { valueNames: [ 'id_name', 'id_town', 'id_give', 'id_comm', 'id_paid', 'id_goal', { name: 'id_perc', attr: 'data-perc' }, ], //sortFunctionで自作関数を呼ぶように指定 sortFunction: my_sort }; var tableList = new List('tableID', options); //List.jsをsortで呼ばれる関数 function my_sort(itemA, itemB, options){ sort_column = options.valueName; v1 = itemA.values()[sort_column]; v2 = itemB.values()[sort_column]; //console.log(options); //console.count("sort count"); //ソートに使う関数を決める。とりあえずカラム名べた書き。 if( sort_column == 'id_name' || sort_column =='id_town'|| sort_column =='id_perc'){ return my_naturalsort(v1,v2); }else{ return my_numbersort(v1,v2); } } //List.jsのソートを呼ぶだけの関数 function my_naturalsort(a,b){ return tableList.utils.naturalSort(a,b) } //文字列処理をしてからList.jsのソートを呼ぶ関数 function my_numbersort(a,b){ console.log('A=%s, B=%s, result=%s', a,b, my_naturalsort(a,b)); s1 = a.replace( '$', '' ).replace(',',''); s2 = b.replace( '$', '' ).replace(',',''); console.log('A=%s, B=%s, result=%s ', s1,s2, my_naturalsort(s1,s2)); f1 = parseFloat(s1); f2 = parseFloat(s2); console.log('A=%s, B=%s', f1,f2, my_naturalsort(f1,f2)); return my_naturalsort(f1, f2); } </script>
おまけ
ソート指定したカラムの値が同じときに、パーセントの降順で並ぶサンプルを作りました。参考にどうぞ。https://github.com/kanaxx/listjs_sample/blob/master/numbersort.html
コメント
コメントを投稿