設定
コードを簡潔に保つために、まずはリスト1のソースコードから始めます。これは完全なアプリケーションのモックアップとして機能するもので、4つのDIVを含む単純なWebページです。4つのDIVは、ユーザーが操作する視覚アイテムを表します。このページがどのように表示されるかを図1に示します。

<html>
<head>
<script src="lib/jquery-1.2.6.js"></script>
<script src="lib/jquery-ui-core-drag-drop-select-1.5.3.js"></script>
<script src="lib/jquery.mousewheel.js"></script>
<link rel="stylesheet"
href="css/demo.css"
type="text/css">
<title>Mockup</title>
<script>
$(document).ready(function() {
// our JavaScript code will go here
});
</script>
</head>
<body>
<h1>Mockup</h1>
<p>
This is the mockup application
that we are going to enrich.
</p>
<div id="container">
<div id="box1" class="box">Blue</div>
<div id="box2" class="box">Red</div>
<div id="box3" class="box">Yellow</div>
<div id="box4" class="box">Green</div>
</div>
</body>
</html>
要素のドラッグと移動
要素のドラッグと移動は、デスクトップパラダイムにより近づくために最初に追加しなければならない機能です。jQuery UIのおかげで、これを行うのはとても簡単です。次のコードをモックアップページのheadセクションに追加するだけでよいのです。
<html>
<head>
<!-- ... omissis -->
<script>
$(document).ready(function() {
$('.box').draggable({
opacity: 0.5,
cursor: 'move',
zIndex: 10000
});
});
</script>
<style type="text/css" media="screen">
.box {
cursor: move;
}
</style>
</head>
<!-- ... omissis -->
</html>
このコードでは、box CSSクラスを持つすべての要素に対してdraggable()ミューテータメソッドを使用しています。このメソッドは、当該のDOM要素がマウスのクリックとドラッグを感知するようにします。
ドラッグ操作は一連のオプションでカスタマイズすることができます。この例では、ドラッグの最中にアイテムを半透明にすること、操作の目的を分かりやすく示す特別なカーソルを表示すること、そしてドラッグされるアイテムを他のものより手前に表示すること(z-indexの値を大きくすることで実現)を宣言しています。これでアイテムをページの中であちこちに移動させることができます(図2を参照)。

公式ドキュメントに記述されているように、ドラッグ中のさまざまな段階で通知を受けるリスナをアタッチすることもできます。これを利用してグループドラッグ(1つの要素をドラッグすると複数の要素が同時に移動する)を実現することができます。この機能は選択管理とともに後で使用します。それにより、ユーザーがデスクトップアプリケーションの場合と同じように、ページ上のアイテムを選択して移動できるようになります。
グループドラッグを実装するには、3つのリスナを追加する必要があります。この3つはそれぞれマウスドラッグの始まり、最中、終わりに対応するものです。これらのリスナは移動するすべての要素の相対位置を記録し、カーソルの下にある要素がドラッグされている間は、関連する要素の位置を継続的に更新します。このコードは少し長くなるので、リスト2に示してあります。サンプルコードには完全な例が含まれています。
<html>
<head>
<!-- ... omissis -->
<script>
$(document).ready(function() {
// define which elements will move
// concurrently with a dragged one.
var dragGroups = {
// dragged item : affected items
'box1' : [ 'box2' ],
'box2' : [],
'box3' : [ 'box1', 'box4'],
'box4' : []
};
$('.box').draggable({
opacity: 0.5,
cursor: 'move',
zIndex: 10000,
// figure out all the initial positions
// for the affected elements, relative to
// the one being dragged, and store them.
// We use the data() function to store
// temporary information on the objects themselves.
start: function(ev, ui) {
ids = dragGroups[ui.helper[0].id];
for (var i = 0; i < ids.length; i++) {
$('#' + ids[i]).data(
"top0",
parseInt($('#' + ids[i]).css("top"),10) -
parseInt($(ui.helper[0]).css("top"),10));
$('#' + ids[i]).data(
"left0",
parseInt($('#' + ids[i]).css("left"),10) -
parseInt($(ui.helper[0]).css("left"),10));
}
},
// whenever the dragged item moves, update
// the positions of all the affected items,
// updating their position with the same relative offset.
drag: function(ev, ui) {
ids = dragGroups[ui.helper[0].id];
for (var i = 0; i < ids.length; i++) {
if (ids[i] != ui.helper[0].id) {
$('#' + ids[i]).css(
'top',
$('#'+ids[i]).data("top0") + ui.position.top);
$('#' + ids[i]).css(
'left',
$('#'+ids[i]).data("left0") + ui.position.left);
}
}
},
// cleanup temporary data at the end
stop: function(ev, ui) {
ids = dragGroups[ui.helper[0].id];
for (var i = 0; i < ids.length; i++) {
$('#'+ids[i]).removeData("top0");
$('#'+ids[i]).removeData("left0");
}
}
});
});
</script>
<style type="text/css" media="screen">
.box {
cursor: move;
}
</style>
</head>
<body>
<!-- ... omissis -->
</body>
</html>
