1. Home
  2. JavaScript
  3. jQuery
  4. jQuery UIを使った要素のドラッグアンドドロップ(複数選択も)

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

  • 公開日
  • カテゴリ:jQuery
  • タグ:JavaScript,Frontend,jQuery,jQuery-UI,Draggable,Droppable,Selectable
jQuery UIを使った要素のドラッグアンドドロップ(複数選択も)

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

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

Contents

  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つ表示され、これを自由にドラッグできるようになります。

See the Pen <a href="https://codepen.io/rito328/pen/ZEojaqq"> jQuery</a> by rito (<a href="https://codepen.io/rito328">@rito328</a>) on <a href="https://codepen.io">CodePen</a>.

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

<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 をバインドします。

See the Pen <a href="https://codepen.io/rito328/pen/oNdMpNb"> 02 Droppable | jQuery UI / Drag and Drop</a> by rito (<a href="https://codepen.io/rito328">@rito328</a>) on <a href="https://codepen.io">CodePen</a>.

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

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

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

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>03 Selectable | 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 イベント発火時には、選択状態を解除しています。

See the Pen <a href="https://codepen.io/rito328/pen/mdLjpVw"> 03 Selectable | jQuery UI / Drag and Drop</a> by rito (<a href="https://codepen.io/rito328">@rito328</a>) on <a href="https://codepen.io">CodePen</a>.

まとめ

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

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

Author

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級