Now browsing the archives for 9月, 2008.
Firefox 3.1 の新しいドラッグ&ドロップ API の基本的な使い方 (その2~ドラッグ処理)
その1~イベントハンドラの追加から引き続き、ドラッグ元の要素をドラッグ開始した際に、転送データをセットする処理を追加する。
DataTransfer オブジェクト
ドラッグした際に転送データをセットする処理や、ドロップした際に転送データを取得する処理は、 DataTransfer オブジェクト (event.dataTransfer) によって行う。
ドラッグ元をドラッグ開始時、つまり dragstart イベント発生時、転送データをセットするには、 DataTransfer オブジェクトの setData メソッドを使用する。 setData メソッドの第1引数は転送データの形式、第2引数は転送データの値(文字列に限る)である。転送データの形式は、単純な文字列であれば「text/plain」、URL(複数も可)であれば「text/url-list」といった値を用いる。もちろん、一度のドラッグで複数の形式の転送データをセットすることも可能である。
サンプルコード (JavaScript)
handleDragEvents 関数へ以下のような処理を追加する。
case "dragstart":
// 転送データをセットする
event.dataTransfer.setData("text/url-list", "http://www.mozilla.org/");
event.dataTransfer.setData("text/plain", "http://www.mozilla.org/");
break;
動作確認
ドラッグ元をドラッグして dragstart, drag, dragend の3つのイベントが発生することを確認してください。
現段階ではドロップ先の処理が未完ですので、ドラッグ時の転送データが正しくセットされていることを確認するために、 Firefox のロケーションバーなどにドロップするか、メモ帳などの別アプリへドロップして、「http://www.mozilla.org/」という文字列が貼り付けされることを確認してください。
参考
DataTransfer オブジェクトの詳細:
DataTransfer – MDC
nsIDOMDataTransfer.idl
転送データの形式の詳細:
Recommended Drag Types – MDC
関連記事
Firefox 3.1 の新しいドラッグ&ドロップ API の基本的な使い方 (その1~イベントハンドラの追加)
Firefox 3.1 の新しいドラッグ&ドロップ API の基本的な使い方 (その2~ドラッグ処理)
Firefox 3.1 の新しいドラッグ&ドロップ API の基本的な使い方 (その3~ドロップ処理)
Firefox 3.1 の新しいドラッグ&ドロップ API の基本的な使い方 (その1~イベントハンドラの追加)
Firefox 3.1 (b1pre) にて HTML 5 のドラッグ&ドロップ API が実装され、 HTML の Web アプリ、 XUL の拡張機能のいずれからも同じように利用可能となった。
拡張機能開発者としては、ドラッグ&ドロップに関する各種処理を、 XPCOM サービスの nsIDragService や面倒くさい nsDragAndDrop.js を使わずに、単純な DOM の API のみで記述できるようになったので、非常にありがたい。
ドラッグ&ドロップのイベント
ドラッグ&ドロップ操作時、ドラッグ元の要素とドロップ先の要素において、以下のようなイベントが発生する。
| イベント名 (event.type) | イベント発生対象 (event.target) | イベント発生のタイミング |
|---|---|---|
| dragstart | ドラッグ元 | ドラッグ開始時 |
| drag | ドラッグ元 | ドラッグ中 |
| dragend | ドラッグ元 | ドラッグ終了時 |
| dragenter | ドロップ先 | ドラッグオーバー開始時 |
| dragover | ドロップ先 | ドラッグオーバー中 |
| dragleave | ドロップ先 | ドラッグオーバー終了時 |
| drop | ドロップ先 | ドロップ時 |
サンプルコード (HTML)
2つの div 要素を配置し、一方をドラッグ元、もう一方をドロップ先とする。
ドラッグ元となる div 要素には、「draggable=”true”」属性をセットしなければならない。ただし、リンク(a 要素)や画像 (img 要素)などは、「draggable=”true”」を指定しなくても自動的にドラッグ可能となる。
ドラッグ元の要素には ondragstart, ondrag, ondragend の3つのイベントハンドラを追加し、ドロップ先の要素には ondragenter, ondragover, ondragleave, ondrop の4つのイベントハンドラを追加する。ただし、必要最低限のドラッグ&ドロップを実装するのであれば、 ondrag, ondragend, ondragleave は省略しても問題ない。
<html>
<head>
<title>Drag and Drop Test</title>
<script type="text/javascript" src="dragdrop.js"></script>
</head>
<body>
<div id="DragSource"
draggable="true"
ondragstart="handleDragEvents(event);"
ondrag="handleDragEvents(event);"
ondragend="handleDragEvents(event);"
style="border: 1px solid black; padding: 50px; margin: 10px;">Drag Source</div>
<div id="DropTarget"
ondragenter="handleDropEvents(event);"
ondragover="handleDropEvents(event);"
ondragleave="handleDropEvents(event);"
ondrop="handleDropEvents(event);"
style="border: 1px solid black; padding: 50px; margin: 10px;">Drop Target</div>
<a href="http://www.mozilla.org/">http://www.mozilla.org/</a>
<img src="http://www.mozilla.org/images/poweredby_200.gif">
</body>
</html>
サンプルコード (XUL)
2つの xul:label 要素を配置し、一方をドラッグ元、もう一方をドロップ先とする。 HTML の場合とほぼ同じであるが、すべての XUL 要素はドラッグ可能となりうるため、「draggable=”true”」属性を指定する必要は無い。
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window title="Drag and Drop Test"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript" src="dragdrop.js" />
<label id="DragSource"
value="Drag Source"
ondragstart="handleDragEvents(event);"
ondrag="handleDragEvents(event);"
ondragend="handleDragEvents(event);"
style="border: 1px solid black; padding: 50px; margin: 10px;" />
<label id="DropTarget"
value="Drop Target"
ondragenter="handleDropEvents(event);"
ondragover="handleDropEvents(event);"
ondragleave="handleDropEvents(event);"
ondrop="handleDropEvents(event);"
style="border: 1px solid black; padding: 50px; margin: 10px;" />
</window>
サンプルコード (JavaScript)
JavaScript のソースコードは、 HTML と XUL の両者に共通となる。また、動作させるために chrome 権限は必要ない。
今回はとりあえず以下のような雛形的なイベントハンドラの処理を作っておき、あとで処理を追加する。
なお、サンプルコードでは window.dump メソッドを使用する。
function handleDragEvents(event) {
dump("[" + event.target.id + "] " + event.type + "
");
switch (event.type) {
case "dragstart":
break;
case "drag":
break;
case "dragend":
break;
}
}
function handleDropEvents(event) {
dump("[" + event.target.id + "] " + event.type + "
");
switch (event.type) {
case "dragenter":
case "dragover":
break;
case "dragleave":
break;
case "drop":
break;
}
}
動作確認
現段階ではドラッグ元をドラッグ開始した際の dragstart イベントしか発生しませんが、実際にドラッグしてイベントが発生することを確認してください。
参考
関連記事
Firefox 3.1 の新しいドラッグ&ドロップ API の基本的な使い方 (その1~イベントハンドラの追加)
Firefox 3.1 の新しいドラッグ&ドロップ API の基本的な使い方 (その2~ドラッグ処理)
Firefox 3.1 の新しいドラッグ&ドロップ API の基本的な使い方 (その3~ドロップ処理)
nsIConsoleService
// サービス取得
var consoleSvc = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
// エラーコンソールへの出力内容を消去
consoleSvc.reset();
// #1 Components.utils.reportErrorによるのエラーメッセージ出力
Components.utils.reportError("error #1");
// #2 nsIConsoleService.logStringMessageによるエラーメッセージ出力
consoleSvc.logStringMessage("error #2");
// #3 nsIConsoleService.logMessageによるエラーメッセージ出力
var err = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError);
err.init("error #3", null, null, null, null, err.errorFlag, null);
consoleSvc.logMessage(err);
// エラーコンソールへの出力内容を列挙
var msgs = {};
consoleSvc.getMessageArray(msgs, {});
msgs.value.forEach(function(msg) {
dump("---
");
if (msg instanceof Ci.nsIScriptError) {
// [JavaScript Error]
msg.QueryInterface(Ci.nsIScriptError);
dump(
msg + "
" +
"errorMessage => " + msg.errorMessage + "
" +
"sourceName => " + msg.sourceName + "
" +
"sourceLine => " + msg.sourceLine + "
" +
"lineNumber => " + msg.lineNumber + "
" +
"columnNumber => " + msg.columnNumber + "
" +
"flags => " + msg.flags + "
" +
"category => " + msg.category + "
"
);
}
else {
// [xpconnect wrapped nsIConsoleMessage]
dump(
msg + "
" +
"message => " + msg.message + "
"
);
}
});
リファレンス
nsIConsoleService – MDC
nsIConsoleService.idl
nsIConsoleMessage.idl
nsIScriptError.idl