Dropper
以下は、Mac OS X 10.4.11 上の Xcode 2.5 で説明しています。このウィジェットは、BlankWidgetで解説したことは繰り返しませんので、そちらを参照してください。
1 ウィジェット
Dropper.wdgt は、以下のようなウィジェットです。
ボックス内のメッセージは「Finder から項目をドラッグし、Dashboard を表示させ、それからこのウィジェット上でドロップしてください」です。Finder から out.png という名前の画像ファイルをためしにドラッグ&ドロップすると以下のようになります。
そのファイルのパスが表示されました。
2 ファイル構成
このサンプルのファイル構成は以下のようになります。
Default.png は、ウィジェットに表示されている背景の緑色の矢印画像です。top.png と bottom.png は、文字が表示されている真ん中のボックスの一番上と一番下の角がまるくなっている所の画像です。middle.png は高さ 1 ピクセルの画像で、文字表示部分の真ん中を埋めるための画像です。
Info.plist の最初に AllowFileAccessOutsideOfWidget キーが値 TRUE とともに置かれていることに注意してください。これは、このウィジェットがドラッグされたファイルにアクセスするために必要なものです。ウィジェットがウィジェット外部にあるファイルにアクセスする必要がある場合、このキーを TRUE にしなければなりません。それ以外の場合はこのキーはなくてかまいません。他のキーは、BlankWidget と同じです。主要 HTML は Dropper.html に指定されています。
3 Dropper.html
それでは、主要 HTML ファイルを見てみます(空行は除去して詰めています)。
Dropper.html
<!-- Dropper.wdgt / Dropper.html
このサンプルウィジェットは、ウィジェット内でドラッグ&ドロップを処理する方法を示す
ここで重要なのは、4 つのドラッグ&ドロップ監視で、それぞれ以下の特定イベントで呼ばれる
ondragenter
ondragover
ondrop
ondragleave
これらの監視に独自のハンドラを割り当て、そのなかで必要な機能を実行する
読み込んだり操作できるファイル URL の取得法はこのウィジェットの JavaScript ファイルを参照 -->
<html>
<head>
<!-- このウィジェットのための CSS -->
<style type="text/css">
@import "Dropper.css";
</style>
<!-- このウィジェットのための JavaScript -->
<script type='text/javascript' src='Dropper.js' charset='utf-8'/>
</head>
<!-- ドラッグ&ドロップハンドラは body に対してセットアップされていることに注意
これらのイベントのどれかが起こったら関連するハンドラが呼び出される -->
<body ondragenter='dragenter(event);' ondragover='dragover(event);'
ondrop='dragdrop(event)' ondragleave='dragleave(event)'>
<img id="arrow" src="Default.png" > <!-- ウィジェットの背景画像 -->
<!-- 「info window」は、このウィジェットが出力する情報を表示する -->
<div class="theInfo">
<img src="images/top.png">
<div class="infoWrap">
<div id="infoLabel">Drag an item from Finder,
show Dashboard, and drop it on this Widget.</div>
<div id="infoURL"></div>
</div>
<img src="images/bottom.png">
</div>
</body>
</html>
構造は単純です。コメントに書かれているように body 要素に対して、ドラッグ進入、ドラッグ移動、ドロップ、ドラッグ脱出に対してハンドラが設定されていることに注意してください。body 内には背景画像を置き、そして情報を表示する div 要素を置き、その div 要素内に top.png を表示する image 要素、div 要素、bottom.png を表示する image 要素という順番で要素を置き、真ん中の div 内部に最初に表示されるラベルと、infoURL という id をもつテキストをもたない空の div を置いています。
4 Dropper.css
スタイルシートを見てみましょう。
Dropper.css
...(省略)...
.infoWrap {
background: url("images/middle.png");
padding-right: 9px;
padding-left: 9px;
width: 134px;
}
#infoLabel {
font: 9px "Lucida Grande";
font-weight: bold;
color: white;
padding-top: 4px;
padding-bottom: 2px;
text-align: center;
}
#infoURL {
font: 11px "Courier New";
font-weight: bold;
color: white;
word-wrap: break-word;
padding-top: 2px;
padding-bottom: 4px;
}
id 属性が infoWrap は top.png と bottom.png を表示する 2 つの image 要素にはさまれていました。ここで背景として、middle.png が指定されています。そこでこの部分の高さ分、背景が繰り返され、top.png と bottom.png とつながって、角のまるい長方形が表示されることになります。
infoLabel は最初に表示されている文字の部分です。次の infoURL は最初はテキストがありません。
5 Dropper.js
このスクリプトには、ドラッグ&ドロップを扱ういくつかの関数が収められています。まず進入したときに呼ばれる関数を見てみます。
Dropper.js > dragenter
// dragenter、dragover、dragleave 関数は実装されているものの使用されない
// これらは、ウィジェットに進入したとき、画像を変更したいなら使うことができる
function dragenter (event)
{
event.stopPropagation();
event.preventDefault();
}
コメントに書かれているとおり、イベントがこれ以上処理されないようにしているほかは、何も行っていません。ついでにドラッグ移動、ドラッグ脱出も見てみます。
Dropper.js > dragover・dragleave
function dragover (event)
{
event.stopPropagation();
event.preventDefault();
}
function dragleave (event)
{
event.stopPropagation();
event.preventDefault();
}
同様に何も行っていません。それでもドロップされた時の関数を見てみます。
Dropper.js > dragover・dragleave
// 画像ドロップに対するイベントハンドラ。
// このハンドラは画像 URL を取得し、それをウィジェット内に置こうとする
function dragdrop (event)
{
var uri = null;
try {
uri = event.dataTransfer.getData("text/uri-list"); // URL の読み込みを試みる
} catch (ex)
{
}
// 取得が成功したら
if (uri)
{
document.getElementById("infoLabel").innerText = "That item's URL is:";
// 新しいラベルテキストを追加
document.getElementById("infoURL").innerText = uri; // ファイル URL を表示
}
event.stopPropagation();
event.preventDefault();
}
まずエラー処理ブロックが設定されています。ただし、ここではエラー処理は行われていません。エラーが起こった場合、catch(ex) 内でエラー処理を行います。URL の取得に成功し null でなかったら、ラベルテキストを最初に表示されている文字列でなく、項目の URL を表示しているという表示にしています。次に、取得したファイル URL を表示しています。この部分は最初に空だったところです。それからイベントの伝播を防いでいます。
ドロップ処理において、イベントの dataTransfer が使われています。これについては、『Safari JavaScript リファレンス』の『Events』を見てください。ちなみに、コピー・ペースト操作は clipboardData というプロパティが使われます。ここで getData メソッドが使われていますが、これは引数に MINE タイプをとります。ここでは、URL のリストを取得しています。このメソッドは、onDrop または onPaste ハンドラで指定された関数内からのみ使えることに注意してください。これは Dashboard だけでなく、Safari 1.3 以降で使用可能です。
6 まとめ
このサンプルは、非常に単純なドラッグ&ドロップ操作を示しています。JavaScript ファイルは、コピーして使われることを考慮して通常実装されるだろうハンドラが何も行われない状態で実装されています。これを参考にすれば、独自のドラック&ドロップ処理を行えるでしょう。
管理人:神吉 秀典 E-mail: