RitoLabo

jQuery UIを使った要素のドラッグアンドドロップ(複数選択も)

  • 公開:
  • カテゴリ: JavaScript jQuery
  • タグ: JavaScript,Frontend,jQuery,jQuery-UI,Draggable,Droppable,Selectable

jQueryには数えきれないくらいのライブラリが開発されており、便利なものがたくさんありますが、jQueryプロジェクト、いわゆる公式のjQueryチームが開発したjQuery UIというライブラリがあります。

今回はjQuery UIを使って、要素のドラッグアンドドロップを実装します。

アジェンダ
  1. 開発環境
  2. jQuery UI
  3. インタラクション
  4. 要素をドラッグする
  5. 目的の場所へドロップする
  6. 複数の要素をドラッグする

開発環境

今回の開発環境は以下の通りです。

  • HTML5
  • CSS3
  • JavaScript
  • jQuery v3.3.1
  • jQuery UI v1.12.1

jQueryとjQuery UIのコアソースに関しては今回のサンプルソースもしくは公式からダウンロードするかCDNを使用してください。

尚、リセット用のCSSとして、meyer-resetのCDNを使用します。

jQuery UI

jQuery UIは、jQueryの拡張ライブラリです。これを導入する事でさらに機能を追加でき、よりインタラクティブな操作を行う事が出来ます。

jQuery UIは拡張ライブラリなので、単体では動作しません。jQueryと一緒に読み込む事で、その機能を使う事が出来ます。

読み込み順も決まっていて、jQuery→jQuery UIの順番で読み込みます。

<script src="jquery.js"></script>
<script src="jquery-ui.js"></script>

インタラクション

jQuery UIを使ってドラッグアンドドロップを行うには、大きく3つのインタラクションを用います。

Draggable
ドラッグに関するインタラクション
Droppable
ドロップに関するインタラクション
Selectable
セレクトに関するインタラクション

これから、これらを使ってドラッグアンドドロップを実装していきます。

要素をドラッグする

まずはミニマムで動作させてみます。ドラッグに関してはDraggableを使います。ソースコードは以下のようになります。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>01 Draggable | jQuery UI / Drag and Drop</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
</head>
<body>
<style>
body {
margin: 20px;
}
.item {
padding: 10px;
width: 80px;
height: 80px;
background-color: #2e6da4;
color: #FFFFFF;
}
.item:hover {
cursor: pointer;
}
</style>

<div id="container">
<div class="item">
<p>ドラッグしてください</p>
</div>
</div>

<script src="/js/jquery-3.3.1.min.js"></script>
<script src="/js/jquery-ui-1.2.1.min.js"></script>
<script>
$(function() {
$('.item').draggable();
});
</script>
</body>
</html>

これをブラウザで動作させると正方形のブロックが1つ表示され、これを自由にドラッグできるようになります。

ドラッグを動作させているのは以下の部分になります。

<script>
$(function() {
$('.item').draggable();
});
</script>

クラス名 item の要素に対してdraggableをバインドしています。これだけで、自由にドラッグを行う事が出来るようになります。

目的の場所へドロップする

次に、ドラッグした要素を目的の場所へドロップさせます。ドロップに関してはDroppableを使います。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>02 Droppable | jQuery UI / Drag and Drop</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
</head>
<body>
<style>
body {
margin: 20px;
}
.item {
width: 100px;
height: 100px;
background-color: #2e6da4;
}
.item:hover {
cursor: pointer;
}
.drop_area {
margin-top: 50px;
width: 200px;
height: 200px;
border: 1px solid #3a945b;
background: #f0fff0;
}
.drop_area p {
margin: 10px;
}
</style>

<div id="container">
<div class="item">
<p>ドラッグしてください</p>
</div>

<div class="drop_area">
<p>ドロップエリア</p>
</div>
</div>

<script src="/js/jquery-3.3.1.min.js"></script>
<script src="/js/jquery-ui-1.2.1.min.js"></script>
<script>
$(function() {
$('.item').draggable();
$('.drop_area').droppable({
activate: function(e,ui) {
$(this)
.find("p")
.html("ドラッグが開始されました");
},
over: function(e,ui) {
$(this)
.css('background', '#e0ffff')
.css('border', '2px solid #00bfff')
.find("p")
.html("ドロップエリアに入りました" );
},
out: function(e,ui) {
$(this)
.css('background', '#ffffe0')
.css('border', '2px solid #ffff00')
.find("p")
.html("ドロップエリアから外れました");
},
drop: function(e,ui) {
$(this)
.addClass("ui-state-highlight")
.css('background', '#fdf5e6')
.css('border', '2px solid #ffa07a')
.find( "p" )
.html( "ドロップされました" );
}
});
});
</script>
</body>
</html>

先ほどと同じようにして、ドラッグ対象にDraggableをバインドします。そして、ドロップされる要素に対してDroppableをバインドします。

ドロップエリア

動作がわかりやすいように引数にイベントを設定しているので、ドラッグ対象をドロップ領域へ動かすとそれに伴ってドロップ領域の表示が変わる事が確認できます。例えばここのイベントを発火させた際に要素の追加などを行えば、ドラッグアンドドロップでの要素追加などが実現できます。

複数の要素をドラッグする

現状では複数の要素をまとめてドラッグできません。複数の要素をドラッグできるようにするには、Selectableを併用します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>02 Droppable | jQuery UI / Drag and Drop</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
</head>
<body>
<style>
body {
margin: 20px;
}
.item {
padding: 10px;
width: 80px;
height: 20px;
border: 1px solid #2e6da4;
background-color: #7da8c3;
color: #FFFFFF;
}
.item:hover {
cursor: pointer;
}
.item p {
display: inline-block;
}
.drop_area {
margin-top: 50px;
width: 200px;
height: 200px;
border: 1px solid #3a945b;
background: #f0fff0;
}
.drop_area p {
margin: 10px;
}
.ui-selected {
background-color: #1cc7ff;
}
.ui-selectable-helper{
position: absolute;
z-index: 100;
border:1px dotted black;
}
</style>

<div id="container">
<div class="item_area">
<div class="item">
<p></p>
</div>
<div class="item">
<p></p>
</div>
<div class="item">
<p></p>
</div>
</div>

<div class="drop_area">
<p>ドロップエリア</p>
</div>
</div>

<script src="/js/jquery-3.3.1.min.js"></script>
<script src="/js/jquery-ui-1.2.1.min.js"></script>
<script>
$(function() {
$('.item_area').selectable({
cancel: "p",
selected: function(e, ui) {
$(ui.selected).draggable().draggable('enable');
}
});
$('.item').draggable({
snap: true,
drag: function(e,ui){
$('.ui-selected').each(function(){
$(this).css({
top: ui.position.top,
left: ui.position.left
});
});
},
stop: function(e,ui) {
$('.ui-selected').each(function(){
$(this).selectable().selectable('destroy');
$(this).draggable().draggable('disable');
});
}
}).draggable('disable');

$('.drop_area').droppable({
activate: function(e,ui) {
$(this)
.find("p")
.html("ドラッグが開始されました");
},
over: function(e,ui) {
$(this)
.css('background', '#e0ffff')
.css('border', '2px solid #00bfff')
.find("p")
.html("ドロップエリアに入りました" );
},
out: function(e,ui) {
$(this)
.css('background', '#ffffe0')
.css('border', '2px solid #ffff00')
.find("p")
.html("ドロップエリアから外れました");
},
drop: function(e,ui) {
$(this)
.addClass("ui-state-highlight")
.css('background', '#fdf5e6')
.css('border', '2px solid #ffa07a')
.find( "p" )
.html( "ドロップされました" );
}
});
});
</script>
</body>
</html>

ポイントを解説します。

$('.item_area').selectable({
cancel: "p",
selected: function(e, ui) {
$(ui.selected).draggable().draggable('enable');
}
});

selectableをバインドします。selectedイベント発火時に、ドラッグを有効化しています。

$('.item').draggable({
snap: true,
drag: function(e,ui){
$('.ui-selected').each(function(){
$(this).css({
top: ui.position.top,
left: ui.position.left
});
});
},
stop: function(e,ui) {
$('.ui-selected').each(function(){
$(this).selectable().selectable('destroy');
$(this).draggable().draggable('disable');
});
}
}).draggable('disable');

draggableをバインドします。最後の行でバインド時はドラッグを無効にしています。こうする事で、複数選択が行えるようにしています。

dragイベント発火時に、選択した要素全てにドラッグで移動している座標を当てて要素を移動させます。

stopイベント発火時には、選択状態を解除しています。

ドロップエリア

まとめ

以上で作業は完了です。ドロップアンドドラッグに関しては、他のサードパティのライブラリよりも細かい動きや制御を行えるので是非試してみてください。

尚、今回のサンプルソースはGithubにあげてあります。
rito-nishino/jquery-ui-sample-drag-and-drop