HTML の表を,列名をクリックしてソートできるようにしたい.
というようなニーズは結構あって,実際いろんなところでそういう機能を実現する JavaScript のコードが公開されている.いくつか当たってみた中で,一番気に入ったのはこれ (の試作5)
気に入った理由は,
という辺り.ありがたく使わせて頂いております.
実際の表は,<td> の中にテキストが直接書かれているとは限らなく,たとえば <a> で囲まれたテキストが書かれてたりとかすることもあるわけで,一般にはテキストに行き着くまで DOM ツリーを再帰的にたどってやる必要がある.データ取得関数 getfn が分離されているので,こんなコードを書いて getfn として渡してやることにした.
function byStrNoCase (cell){ return extractText(cell) . toLowerCase() ; } function byInt (cell) { return parseInt(extractText(cell) ) ; } function extractText(node) { var text = ' ' ; if (node. nodeType = = 3) { / / TEXT_ NODE text = node. nodeValue; } else if (node. hasChildNodes() ) { var n = node. childNodes. length; for (var i = 0; i < n; i+ + ) { text = text + extractText(node. childNodes[i] ) ; } } return text; }
JavaScript の Array の sort()
一番安直にやるには,ソート対象の要素にプロパティとして元の順番も持たせておいて,比較して引き分けだったら元の順番を保存するような比較関数 cmpfn を渡してやればよい.
のだが,元のコードだと,getfn が返した値を Object 型に変換してそれをソートしているので,比較の結果として引き分けにならない.しかたないので,getfn の返した値を Object 型に変換するのではなく,Object のプロパティとして getfn の返した値を持たせてやるように書き換えて使っている.つまり
for(var i=0; i<N; i+ + ) x[i] = Object( getfn( rows[i] . cells[index] ) ) , x[i] . row= rows[i] ;
の部分を
for(var i=0; i<N; i+ + ) { x[i] = new Object; x[i] . v = getfn(rows[i] . cells[index] ) ; x[i] . row = rows[i] ; x[i] . idx = i; }
にしてやる.cmpfn は
function cmpAsc(a,b) { if (a. v = = b. v) { if (a. idx = = b. idx) { return 0; / / can' t happen } else if (a. idx > b. idx) { return 1; } else { return - 1; } } else if (a. v > b. v) { return 1; } else { return - 1; } } function cmpDesc(a, b) { return cmpAsc(b, a) ; }
みたいな感じ.
最終更新時間:
*
[Christian]
Thanks for the great info dog I owe you ... (2012-12-30 13:35:14)