jQuery UIのsortableを使ってtable要素を並び替える

sortableの基本的な使い方はこちらを参照。
jQuery UIのsortableを使ってドラッグアンドドロップで並び替え

間違った例

一番シンプルに書こうとするとこうなるかと思います。

HTML
<table id="sortable-table">
	<tr>
		<th>番号</th><th>項目</th><th>備考</th>
	</tr>
	<tr>
		<td>1</td><td>項目1</td><td></td>
	</tr>
	<tr>
		<td>2</td><td>項目2</td><td></td>
	</tr>
	<tr>
		<td>3</td><td>項目3</td><td>なし</td>
	</tr>
</table>
javascript
$(function(){
	$('#sortable-table').sortable();
});

これだとうまくいきません。

リンク先の例でもtheaderタグ、tbodyタグをきちんと書いた上で下記のようにやっていますが、どうやらtbodyが曲者のようです。

	$('#sortable-table tbody').sortable();

調べてみると、tableタグを扱う際にはtbodyが必要らしく、最近のブラウザはtableタグの直下にtrがある場合はtbodyを追加してtrをその下に移動させているようです。同様にjQueryでもtbodyを自動的に追加するようです。

で、sortable()の話になるんですが、並び替え対象となる項目はitemsオプションで指定するんですが、デフォルトでは"> *"です。つまり直下の子要素となります。
Sortable API(items)

これらを考えると、大きく二通りの方法で並び替えを実現できそうです。

  • tbodyをちゃんと書く
  • itemsオプションを指定する

以下にサンプルコードを載せておきます。

デモ画面

tbodyに対してsortable()

html
	<table id="sortable-table1">
		<thead>
			<tr>
				<th>番号</th>
				<th>項目</th>
				<th>備考</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td>1</td><td>項目1</td><td></td>
			</tr>
			<!-- 項目2~は省略 -->
		</tbody>
	</table>
css
#sortable-table1 {
	width: 50%;
	border-collapse: collapse;
}
#sortable-table1 td, #sortable-table1 th {
	border: solid 1px black;
}
javascript
$(function(){
	$('#sortable-table1 tbody').sortable();
});

ポイントとしては、javascriptセレクタでtbodyを指定しているところくらいです。
おそらくこれが最もシンプルな方法かなと思います。

itemsオプションで指定

html、css

上の例と同じ(idは"sortable-table2"に変えています)

javascript
$(function(){
	$('#sortable-table2').sortable({"items": "tbody tr"});
});

これは上の例とは違って、セレクタはtableを指定しています。その上でitemsオプションで"tbody tr"を指定することで目的を達成できます。
この方法は、少し応用が利きます。

並び替え可能な項目にcssクラスを設定

html
	<table id="sortable-table3">
			<tr>
				<th>番号</th>
				<th>項目</th>
				<th>備考</th>
			</tr>
			<tr class="sortable-tr">
				<td>1</td><td>項目1</td><td></td>
			</tr>
			<!-- 項目2~4は省略 -->
			<tr>
				<td>5</td><td>並び替え不可</td><td></td>
			</tr>
	</table>

ここではあえてtheadとtbodyタグは削除しています。
代わりに項目1~4のtrに"sortable-tr"クラスを指定しています。

css

上の例と同じ(idは"sortable-table3"に変えています)

javascript
$(function(){
	$('#sortable-table3').sortable({"items": "tr.sortable-tr"});
});

こうすることによって、並び替えしたくない要素がある場合にも対応可能です。例えば、最後に「1行追加」ボタンを設置したい場合等はこのように実現できます。

もう一歩

デモ画面を見てもらって気になった人もいると思いますが、ドラッグしようとしているときの要素の幅が縮んでいます。
それについては続きにて

JavaScript 第6版

JavaScript 第6版