ほんじゃーねっと

おっさんがやせたがったり食べたがったりする日常エッセイ

jQueryでリスト・テーブル操作 - 行の上下移動

ここ数件のプロジェクトでリストやテーブルの行追加、削除やソート、上下移動などの処理を書く事があったので、メモしておく。


今回は行の上下移動。
リストの各行に「上へ」「下へ」というボタンなりリンクなりアイコンなりを配置しておき、それをクリックすると対象の行が上下に移動するというもの。


test.html

...
<script type="text/javascript" src="/js/jquery/jquery-1.3.1.min.js"></script>
<script type="text/javascript" src="/js/test.js"></script>
...
<ul id="test-list">
<li class="test-row">
<input type="hidden" name="data" value="1:id1" />
<span class="title">データ1</span>
<a href="#" class="control up-control">上へ</a>
<a href="#" class="control down-control">下へ</a>
</li>
<li class="test-row">
<input type="hidden" name="data" value="2:id2" />
<span class="title">データ2</span>
<a href="#" class="control up-control">上へ</a>
<a href="#" class="control down-control">下へ</a>
</li>
<li class="test-row">
<input type="hidden" name="data" value="3:id3" />
<span class="title">データ3</span>
<a href="#" class="control up-control">上へ</a>
<a href="#" class="control down-control">下へ</a>
</li>
</ul>
...


hidden要素はフォームで変更結果を保存する場合に使う。
value値は「インデックス:データのID」で、インデックスを上下移動する時にjavascriptで更新する。
インデックスデータの保持についてはもう少し洗練された方法がありそうな気がする。


test.js

function update_row_index() {
$("#test-list li").each(function (i) {
var data_input = $('input[name="data"]', this);
var vals = data_input.val().split(":");
data_input.val((i + 1) + ":" + vals[1]);
});
}
$(document).ready(function() {
$("#test-list .up-control").click(function (e) {
e.preventDefault();
var row = $(this).parent();
if (row.not(":first")) {
row.insertBefore(row.prev());
update_row_index();
}
});
$("#test-list .down-control").click(function (e) {
e.preventDefault();
var row = $(this).parent();
if (row.not(":last")) {
row.insertAfter(row.next());
update_row_index();
}
});
});


これで動くはず。
各行が複雑な構造の場合は、parent().parent()l... みたいにしてるけど、もっと簡単に親ノードを呼ぶ方法はないものかな。