WebOS Goodies

WebOS の未来を模索する、ゲームプログラマあがりの Web 開発者のブログ。

WebOS Goodies へようこそ! WebOS はインターネットの未来形。あらゆる Web サイトが繋がり、共有し、協力して創り上げる、ひとつの巨大な情報システムです。そこでは、あらゆる情報がネットワーク上に蓄積され、我々はいつでも、どこからでも、多彩なデバイスを使ってそれらにアクセスできます。 WebOS Goodies は、さまざまな情報提供やツール開発を通して、そんな世界の実現に少しでも貢献するべく活動していきます。
Subscribe       

Google Personalized Homepage ガジェットの作り方 : Drag ライブラリ

本日は、引き続き Google Personalized Homepage ガジェットで使える機能別ライブラリの中から、 Drag ライブラリをご紹介します。このライブラリを使うと、ガジェット中の任意の HTML 要素をドラッグ&ドロップできるようになります。ドラッグされる要素(ソース要素)とドラッグを受け取る要素(ターゲット要素)を指定するだけでよく、他の面倒な処理はライブラリ側にお任せですので、驚くほど簡単に実装できます。ドラッグ&ドロップは直感的な UI を実現するのに非常に効果的ですので、うまく活用して使いやすいガジェットを目指したいところですね。

それでは、さっそく使い方を見ていきましょう。なお、機能別ライブラリの基本事項についてはこちらの記事でご紹介しています。機能別ライブラリにはじめて触れる方は、先にご参照いただくと良いかと思います。

概要

以下で Drag ライブラリの使い方を見ていきますが、説明の都合上、いくつか用語を使っていますので、その定義も兼ねて Drag ライブラリの概要をご紹介します。なお、これらの用語のほとんどは私が勝手に定義したもので、一般的なものではありません。ご了承ください。

Drag ライブラリでドラッグ&ドロップを実現するには、あらかじめソース要素(実際にマウスでドラッグできる要素)とターゲット要素(ドロップを受け取る要素)を _IG_Drag クラス(後述)のオブジェクトに登録しておきます。これらの要素はドラッグ ID と呼ばれるユニークな文字列で識別され、オブジェクト内のソースリストとターゲットリストに格納されます。さらに、必要に応じてドラッグ開始・終了などで実行するコールバック関数も登録します。これで準備は完了です。

後は、ドラッグ&ドロップの制御のほとんどをライブラリが暗黙的に行ってくれます。ソース要素がクリックされると、ソース要素をまるごとコピーして(このコピーをサロゲートと呼びます)、ボタンが離されるまでマウスカーソルと一緒に移動させます。ボタンが離されるとドラッグ終了のコールバックが呼び出され、ソース要素と(ターゲット要素上でドラッグを終えた場合のみ)ターゲット要素の DOM Element が渡されますので、それを元に実際のドキュメントを変更することになります。実際の動作は後のサンプルガジェットで試してみてください。

以上が Drag ライブラリの動作概要です。最低限、ドキュメントロード時にソース要素・ターゲット要素とドラッグ終了コールバック関数を登録するだけで、ドラッグ&ドロップの処理が実現できるわけです。お手軽ですね。

Require 宣言

他の機能別ライブラリと同様、 Drag ライブラリも標準では読み込まれません。利用するには、以下のタグを ModulePrefs の子要素として記述する必要があります。

<Require feature="drag" />

Drag ライブラリの利用に必要なのはこれだけです。他に読み込むべきファイルなどはありません。

オブジェクトの作成

Drag ライブラリも Tabs ライブラリと同様、インターフェースは _IG_Drag クラスにまとめられています。そのため、まず以下のようにしてインスタンスを作成する必要があります。

var drag = new _IG_Drag();

上記のとおり _IG_Drag クラスのコンストラクタは引数をとりません。 __MODULE_ID__ も不要です。

メソッド

以下、 _IG_Drag クラスに実装されているメソッドです。

addSource(<ID>[, ソース要素[, サロゲート]])
ソース要素で指定された DOM オブジェクトをドラッグソースリストに登録し、 ID で指定されたドラッグIDを割り振ります。ソース要素を省略すると、 id 属性が ID と等しい要素を取得してそれを使います。サロゲートHTML 文字列を指定すると、ソース要素のコピーの代わりにそれをサロゲートとして使用します。
removeSource(<ID>)
ドラッグIDが ID である要素をドラッグソースリストから取り除きます。
removeAllSources()
ドラッグソースリストを空にします。
addTarget(<ID>[, ターゲット要素[, 優先度]])
ターゲット要素で指定された DOM オブジェクトをドラッグターゲットリストに登録し、 ID で指定されたドラッグIDを割り振ります。ターゲット要素を省略すると、 id 属性が ID と等しい要素を取得してそれを使います。優先度はターゲットが重なっているときに使用される優先度で、値が大きいほど優先度が高くなります。デフォルトは 0 です。
removeTarget(<ID>)
ドラッグIDが ID である要素をドラッグターゲットリストから取り除きます。
removeAllTargets()
ドラッグターゲットリストを空にします。

プロパティー

_IG_Drag クラスには、ドラッグ&ドロップの状態の取得・設定に使用する多数のプロパティーが定義されています。最低限の処理はコールバックの定義だけで実現できますが、凝った処理をしたいときはこれらのプロパティーの内容を知る必要があるでしょう。以下に簡単にご紹介します。

読み込み専用プロパティー

以下は読み込み専用のプロパティーです。主にドラッグ&ドロップの状態取得に使えます。

isDragging
ドラッグ中のみ true になります。
hasDragged
ドラッグを開始した後にマウスを動かすと true になります。
surrogate
サロゲートとして表示されている要素です。
surrogateInitialX, surrogateInitialY
ドラッグ開始時点のサロゲートの初期座標です。
curSource
現在ドラッグ中のソース要素。ドラッグ中でなければ null。
curTargetId
現在のターゲットのドラッグID。ドラッグ中でなければ null。

読み書き可能プロパティー

以下は値を代入できるプロパティーです。細かな挙動の調整に利用します。

leftMargin, rightMargin, topMargin, bottomMargin
ターゲットが反応する領域をターゲット自体の領域よりも広げるためのマージン。デフォルトは 2 ピクセル。
surrogateOffsetX, surrogateOffsetY
サロゲートの表示開始座標のオフセット。デフォルトは 1 ピクセル。

コールバック

以下はドラッグ&ドロップの処理中に呼び出されるコールバックです。任意の関数を設定しておけば、適切なタイミングでそれらが呼び出されます。

onDragStart = function(<ソース要素>) {}
ドラッグが開始された際に呼ばれます。
onDragTargetHit = function(<新しいターゲット要素>, <最後のターゲット要素>) {}
ドラッグ中、マウスカーソルがターゲット上に入ったときに呼ばれます。
onDragTargetLost = function(<最後のターゲット要素>) {}
ドラッグ中、マウスカーソルがターゲットから外れたときに呼ばれます。
onDragEnd = function(<ソース要素>, <ターゲット要素>) {}
ドラッグが終了した際に呼ばれます。通常、このコールバック関数内でドラッグ&ドロップの結果(要素の移動など)を実際のドキュメントに反映させます。
onDragClick = function(<ソース要素>) {}
ユーザーがドラッグソースリストに登録された要素上で左ボタンを押し、その後まったくマウスカーソルを動かさずに離したとき(つまり単にクリックしたとき)に呼ばれます。ソース要素の onclick イベントの代わりとして使えます。

サンプルガジェット

サンプルとして、テキスト要素をドラッグ&ドロップできるガジェットを作ってみました。左側のボックスに並んでいる「アイテム1」などのテキストを右側のボックスにドラッグ&ドロップで移動させることができます。「アイテム4」だけは登録時にサロゲートを指定していますので、ドラッグ中の表示が変わります。また、コールバックを利用してドラッグ中はボックスの下に「ドラッグ中...」と表示するようにしてみました。大したものではありませんが、試しにいじってみてください。

ソースコードは以下です。

<?xml version="1.0" encoding="UTF-8" ?> 
<Module>
  <ModulePrefs title="Drag"
               title_url="http://webos-goodies.jp/archives/51032489.html"
               height="120">
    <Require feature="drag"/>
  </ModulePrefs>
  <Content type="html">
    <![CDATA[
 
<style type="text/css">
.box { border:solid 1px black; padding: 4px; height:90px; empty-cells:show; vertical-align: top; }
</style>
 
<table style="width:100%; border:none; padding:0px; margin:0px;">
<tbody><tr>
<td id="box1" class="box" width="50%">
<div id="item1">アイテム1</div>
<div id="item2">アイテム2</div>
<div id="item3">アイテム3</div>
<div id="item4">アイテム4</div>
</td>
<td id="box2" class="box" width="50%">
</td>
</tr></tbody>
</table>
<div id="msg"></div>
 
<script type="text/javascript">
var drag_obj = new _IG_Drag();
drag_obj.addSource("item1");
drag_obj.addSource("item2");
drag_obj.addSource("item3");
drag_obj.addSource("item4", _gel("item4"), '<div style="font-size:10px">ドラッグ中の表示は<br/>差し替えられます</div>');
drag_obj.addTarget("box1");
drag_obj.addTarget("box2");
drag_obj.onDragStart = function(source) {
  _gel("msg").innerHTML = "ドラッグ中..."
}
drag_obj.onDragEnd = function(src, tgt) {
  if(src && src.parentNode && tgt && src.parentNode != tgt)
  {
    tgt.appendChild(src);
  }
  _gel("msg").innerHTML = "";
}
</script>
 
    ]]>
  </Content>
</Module>

以上、本日は HTML 要素のドラッグ&ドロップを簡単に実現できる、 Drag ライブラリについてご紹介しました。コールバックをきちんと実装すれば、リストのアイテムをドラッグ&ドロップで並べ替える、なんてことも実現できると思います。今のところこのライブラリを活用したガジェットはあまり見かけないので、狙い目かもしれませんよ(笑)。次回は、ガジェットに短いメッセージを表示する MiniMessages ライブラリをご紹介します。

関連記事

この記事にコメントする

Recommendations
Books
「Closure Library」の入門書です。
詳しくはこちらの記事をどうぞ!
Categories
Recent Articles