jQuery UIのsortableでplaceholderを設定

jQuery UIのsortableでplaceholderオプションを指定すると下図のようにドラッグ先の場所のCSSスタイルを設定することができます。
(図では項目2をドラッグアンドドロップしようとしています)
f:id:kamegu3:20130522223549p:plain

placeholderオプション指定

http://api.jqueryui.com/sortable/#option-placeholder

まずは単純にsortable()呼び出しの際にplaceholderオプションを指定してみます。
デモ画面
※「placeholderオプション指定のみ」を見てください。オン/オフボタンクリックでplaceholderオプションの有効化/無効化を行います。

html
<ul id="sortable-with-placeholder">
	<li class="ui-state-default">項目 1</li>
	<li class="ui-state-default">項目 2</li>
	<li class="ui-state-default">項目 3</li>
	<li class="ui-state-default">項目 4</li>
	<li class="ui-state-default">項目 5</li>
</ul>
javascript
$(function(){
	$('#sortable-with-placeholder').sortable({placeholder: "placeholder"});
});
css
#sortable-with-placeholder {
    padding: 0;
    list-style-type: none;
    width: 50%;
}
.placeholder {
	border: 1px dashed red;
	background-color: pink;
}

placeholderクラスが上のsortable()のオプションで指定されているクラスです。
ちなみに、jQuery UIにはui-state-highlight
というクラスが定義されているようなのでこれを使ってもいいかもしれません。

	$('#sortable-with-placeholder').sortable({placeholder: "ui-state-highlight"});

ただ、このままだとドラッグ中は高さ=0になっているように見えます。そこで解決策を2つ提案します。

解決策1 高さを指定する

デモ画面CSSでheight指定)

CSSで高さを指定すればよさそうです。ただし、placeholderクラスの高さではなく、今回はli要素の高さを指定します。
placeholderクラスの高さだけを指定すると下図のように移動させようとしている項目のサイズと移動先のサイズを一致させるのが難しくなります。そうなると、一覧全体のサイズがドラッグ時と非ドラッグ時で変わってしまうので、見難くなります。
f:id:kamegu3:20130522225715p:plain

次のように変えます。

javascript

何も変えず

css
#sortable-with-placeholder {
    padding: 0;
    list-style-type: none;
    width: 50%;
}
#sortable-with-placeholder li { //これを追加
	height: 15px;
}
.placeholder {
	border: 1px dashed red;
	background-color: pink;
}

ただし、このように高さを指定してしまうと要素の項目名が長くなると文字の漏れが生じてしまいます。

解決策2 forcePlaceholderSizeオプション指定

http://api.jqueryui.com/sortable/#option-forcePlaceholderSize

デモ画面(forcePlaceholderSizeオプション指定)

元のコードからjavascriptを次のように書き換えます。

javascript
$(function(){
	$('#sortable-with-placeholder').sortable({placeholder: "placeholder", forcePlaceholderSize: true});
});

この場合でもplaceholderの高さを指定している場合はそちらが優先されます。

このオプション(forcePlaceholderSize)の使い方はちょっと分かりにくいのでこれであっているかどうか正直自信ないですが、とりあえず問題なさそうです。

以上