連載
» 2008年03月03日 00時00分 公開

パターンとライブラリで作るAjaxおいしいレシピ(5):jQuery UIで実現! Ajaxで複数選択ドラッグ&ドロップ (4/4)

[志田裕樹,アークウェブ株式会社]
前のページへ 1|2|3|4       

ファイルをdraggableにし、初期状態はdisableにしておく

$('.file').draggable({
    containment: '#filer',
    start: onStartDrag,
    drag: onDrag,
    stop: onStopDrag
}).draggable('disable');

 この処理は、ページが読み込まれた際に一度だけ行われるファイルの初期化処理に当たります。ここでは、全ファイルに対してdraggable()を設定しています。この際、ディレクトリの親要素である<div id='filer'>の範囲のみドラッグ可能となるようにしています。onStartDragonDragonStopDragイベントハンドラについては後で解説します。

 ファイルは選択状態にならなければドラッグできないようにしますので、いったんdraggableを設定した後に、'disable'で無効化しています。

選択(または、選択解除)されたファイルのドラッグの有効化(または、無効化)

onSelected: function(e, ui) {
    var file = $(ui.selected);
    file.draggable('enable');
},
onUnselected: function(e, ui) {
    var file = $(ui.unselected);
    file.draggable('disable');
},

 これらのメソッドは、ファイルのドラッグによる選択を行ったときと、選択解除を行ったときに呼び出されます。onSelectedイベントハンドラ、onUnselectedイベントハンドラはそれぞれ下記2つの処理を行っています。

  1. 選択されたファイルのドラッグを有効化
  2. 選択解除されたファイルのドラッグを無効化

dropの条件の設定

isAccept: function(draggable) {
    var oldDirectory = $(draggable).parent().get(0);
    var newDirectory = this.get(0);
    if (newDirectory.id != oldDirectory.id) {
        return true;
    }else {
        return false;
    }
}

 このメソッドはファイルをディレクトリの上に重ねた際に、そのファイルがディレクトリにドロップ可能かどうかを調べるために呼び出されます。このメソッドの中では、ドロップ前後のディレクトリを調べ、ドラッグ前に所属していたディレクトリと同一のディレクトリにドロップしていた場合は、ドロップできないようにしています。「get(0)」は配列の0番目を返すメソッドです。

ドロップされたらそのディレクトリの子要素になるようにすげ替える

onDrop: function(e, ui) {
    var directory = ui.instance.element;
    var files = $('.ui-selected');
    files.appendTo(directory)
         .css('top', '0px')
         .css('left', '0px')
         .removeClass('ui-selected')
         .draggable('disable');
}

 このメソッドはファイルをディレクトリにドロップした際に呼び出されます。ドロップ対象のディレクトリを取得し、すべての選択されたファイルをそのディレクトリ配下に入るようにします。その後、各ファイルの位置を初期化し、その後、選択をすべて解除し、ドラッグを無効化します。jQueryのメソッドチェーンのおかげですっきり書くことができますね。

複数ファイルのドラッグの実装

 最後に、複数ファイルのドラッグの実装について解説していきます。

ドラッグ開始時に開始位置を保持しておく

onStartDrag: function(e, ui) {
    var helper = ui.helper.get(0);
    var parentId = $(helper).parent().get(0).id;
    helper.selectedFiles = $('#' + parentId + ' .ui-selected');
    helper.selectedFiles.each(function() {
        this.startTop = parseInt($(this).css('top'));
        this.startLeft = parseInt($(this).css('left'));
    });
},

 このメソッドはドラッグが開始される際に呼び出されます。まず以下の処理で、「つかんでいるファイル」を取得しています。

    var helper = ui.helper.get(0);

 その後、以下の処理でそのファイルが所属しているディレクトリを取得します。

    var parentId = $(helper).parent().get(0).id;

 そして、以下の処理では、セレクタ部分が、例えば、「#directory1 .ui-selected」といった文字列になるので、これでドラッグ対象となるすべてのファイルを選択できます。

    helper.selectedFiles = $('#' + parentId + ' .ui-selected');

 これらを、「つかんでいるファイル」のオブジェクトに、selectedFilesというプロパティとして保持させています。その後、ドラッグ対象となるすべてのファイルそれぞれに、開始位置を保持させています。

「つかんだファイル」の開始位置からの移動距離の計算

onDrag: function(e, ui) {
    var helper = ui.helper.get(0);
    var topDistance = ui.position.top - helper.startTop;
    var leftDistance = ui.position.left - helper.startLeft;

 このメソッドはドラッグ中に呼び出されます。最初に、現在の「つかんでいるファイル」の位置と開始位置の差を求め、移動距離を計算しています。

「つかんでいない選択中のファイル」の移動

 下記は、上記のコードの続き部分になります。

    helper.selectedFiles.each(function() {
        if (this.selectedFiles == null) {
            var newTop = this.startTop + topDistance;
            var newLeft = this.startLeft + leftDistance;
            $(this).css('top', newTop + 'px')
                   .css('left', newLeft + 'px');
        }
    });
},

 「つかんでいるファイル」には、ドラッグ対象のファイルの配列である、selectedFilesというメンバが設定されていますので、このメンバが設定されていないファイルが、すなわち「つかんでいない選択中のファイル」になります。これらのファイルそれぞれに対して、自分自身の開始位置と「つかんだファイル」の移動距離を足して、その位置に移動をさせています。

ドラッグ終了時の終了処理

onStopDrag: function(e, ui) {
    var helper = ui.helper.get(0);
    helper.selectedFiles = null;
},

 このメソッドはドラッグが終了した際に呼び出されます。ドラッグが終了したら、「つかんだファイル」のselectedFilesのメンバを削除します。

 以上でソースコードの解説は終わりです。

ドラッグ&ドロップによるユーザビリティの向上を

 今回はjQuery UIのドラッグ&ドロップ機能に注目し、個々の使い方を解説し、その後に、要素を複数選択してドラッグ&ドロップを行うサンプルについて解説しました。

 サービスサイト、会員サイト、イントラネットなど、ユーザーにある程度長い時間、Webページ上で作業を行わせるようなサイトでは、ドラッグ&ドロップを利用することで作業効率をアップできるケースがあると思います。jQueryのドラッグ&ドロップ機能は非常にオプションが豊富でカスタマイズがしやすいので、きめ細かなアプリケーションの構築が可能です。ぜひチャンレンジしてみてください(参考:jQueryサンプル

 また、今回は取り上げなかった、Sortable、Resizableも非常に便利です。これらも、気軽に導入し、ユーザービリティ向上に役立てることができるライブラリですので、ぜひ試してみてください。

 今回のすべてのソースコードはこちらになりますサンプルのライセンスはGPL 2となります

著者紹介

プロフィール:志田 裕樹(しだ ゆうき)

株式会社アークウェブ取締役。Webシステムのシステムエンジニアとして開発に従事している。
Ajax、Ruby on Rails等を使用したWeb 2.0的システムの開発実績を持つ。
オープンソースのECサイト用CMS、Zen Cartの日本語コミュニティでコミッターとして活動している。



前のページへ 1|2|3|4       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。