前回までにさまざまな演出効果を紹介してきた。今回からはScript.aculo.usのコンポーネントを紹介していきたい。最初はドラッグ&ドロップを実現するDraggableとDroppablesだ。

なお、Script.aculo.usのバージョンは、新年早々にリリースされた1.8.1である(CHANGELOG)。詳細はWikiページで確認していただきたい。なお、紹介するオプションはすべて省略可能だ。

要素をドラッグ可能にする

new Draggable( IDもしくはDOMオブジェクト, { オプション } );
マウスのドラッグによって、要素の位置を移動できるようにする。ドラッグ中の要素はデフォルトで透明度が0.7に設定されるが、この動作はstarteffect, endeffectオプションを上書きすることで変更できる。

[主なオプション]

名称 値の内容 デフォルト
revert マウスのボタンを放してもドロップされないときは元の位置に戻る false
ghosting ドラッグ中も元の位置に要素を表示する false
snap 要素が移動するときの間隔(ピクセル)
(*)[x, y]またはそれを戻り値とする関数
false
handle ドラッグ可能な要素 false
constraint 移動可能な方向
(*)'vertical'(垂直方向のみ)/'horizontal'(水平方向のみ)を指定可能
――
onStart ドラッグ開始時のイベント処理(関数) ――
onDrag ドラッグ途中のイベント処理(関数) ――
change ドラッグ途中のイベント処理(関数) ――
onEnd ドラッグ終了時のイベント処理(関数) ――
starteffect ドラッグ開始時の演出効果(関数) 定義済み
endeffect ドラッグ終了時の演出効果(関数) 定義済み
reverteffect revert : trueの際の戻り方(関数) 定義済み
(*) onStart, onDrag, onEndは関数の引数がDraggableとイベントオブジェクトだが、changeではそれがDraggableのみとなる
(*) starteffect, endeffect, reverteffectは定義済みだが、ドラッグされる要素を引数とする関数により上書き可能

図1 ドラッグ中は要素の透明度が0.7(デフォルト)に設定される

【例】 ドラッグ時は上下左右に30ピクセルずつ移動し、終了時に'ドラッグ完了'と表示する

 new Draggable( 'demo', {
       snap  : [30, 30],     // [水平方向の移動幅, 垂直方向の移動幅](ピクセル単位)
       onEnd : function( draggable, event )  {
         alert( 'ドラッグ完了' );
       }
 } );

ドロップ可能にする
Droppables.add( IDもしくはDOMオブジェクト, { オプション } );
ドロップ不能にする
Droppables.remove( IDもしくはDOMオブジェクト );

[主なオプション]

名称 値の内容 デフォルト
accept ドロップを受け入れる要素(CSSクラス名もしくはその配列) ――
hoverclass ドラッグされた要素が重なったときに追加するCSSクラス名 ――
onDrop ドロップが完了したときのイベント処理 ――

【例】 class="draggable"を持つ要素をid="droppable"の要素へドロップ&ドロップ可能にする

図2 ドラッグする前

図3 hoverと認識された

図4 ドロップ完了

new Draggable( 'demo', {       // ドラッグされる要素
  onStart : function( draggable, event )  {
    // ドラッグ開始時の初期化
    draggable.element.removeClassName( 'border-red' );
    $( 'droppable' ).style.backgroundColor = 'transparent';
    $( 'droppable' ).innerHTML = 'ここにドロップされる';
  }
} );
Droppables.add( 'droppable', {
  accept :      'draggable',  // ドロップ可能な要素のCSSクラス名(配列も可)
  hoverclass :  'border-red', // hoverと認識されたときに追加されるCSSクラス名
  onDrop : function( draggableElement, droppableElement, event )  {
    // ドロップ完了時の処理
    $( draggableElement ).addClassName( 'border-red' );
    droppableElement.style.backgroundColor = '#ccff99';
    droppableElement.innerHTML = draggableElement.id + 'がドロップされた';
  }
} );

[対象となる要素]
<div id="droppable" class="dashed">ここにドロップされる</div>
<div id="demo" class="draggable">ドラッグ可能にするDraggable</div>

[CSS設定]
.dashed  {
  border : 1px dashed black;
}
.border-red  {
  border : 2px dashed red;   /* hoverと認識されたときやドラッグされた要素に追加される */
}
div#demo, div#droppable  {
  margin : 3px;      padding : 3px;
}
div#demo  {                  /* ドラッグされる要素 */
  /* position は省略 */
  width  : 100px;    height  : 100px;
  background-color : #ffcc99;
}
div#droppable  {             /* ドロップ可能となる要素 */
  /* position は省略 */
  width  : 150px;    height  : 150px;
  background-color : transparent;
}

Draggableによりドラッグ可能になった要素に対応して、ドロップ可能な要素を用意することで、ドラッグ&ドロップを実現するのが、このDroppablesだ。末尾のsを忘れないようにしたい。

Draggableは要素ごとにnewでインスタンスを作成するのに対し、Droppablesでは、add()とremove()によりドロップ可能な要素を登録および削除する。それからDraggableでは、ドラッグ可能な要素はIDを用いた設定が可能なのに対し、Droppablesでは、ドロップ可能な要素はCSSクラス名(HTMLではclass属性の値に含まれる)で設定しなくてはならない。このように、DraggableとDroppablesとでは、名前は似ているが設定の方法は異なる点が多いので、注意していただきたい。

また、図3に示すように、ドロップ可能な要素がDroppablesで指定された要素に重なったhoverの状態と認識されるのは、マウスカーソルがDroppablesで指定された要素の範囲に納まったときであって、要素どうしが重なり合ったときではない。また、hoverオプションで追加されたCSSクラスがhoverと認識されたときに、きちんと画面表示に反映されるように、CSS設定の優先順位を考慮する必要がある。

それから、図4で示すように、ドロップが完了したときの画面表示をどのようにするかも、ユーザーインタフェースを設定する上で考慮すべきところだろう。

Web画面上でドラッグ&ドロップが実現できると、商品を買い物かごに入れるといった直観的な操作をユーザーに提供できるようになる。これを使いこなして表現の幅を広げていただきたい。