HTML5のドラッグ&ドロップAPI、File API、Web Storage

2012年5月8日(火)
飯島 聡(著)山田 祥寛(監修)

ドラッグ&ドロップでのデータの受け渡し

ドラッグ&ドロップ操作は、一般的に、要素の移動、または何らかの情報のコピーのために使用します。よって、ドロップ先でドラッグ元の情報を参照できるようにする必要があります。

ドラッグ&ドロップイベントでは、e.dataTransferプロパティによってDataTransferオブジェクトを取得できます。DataTransferオブジェクトは、ドラッグ要素の情報を管理するためのオブジェクトです。setData/getDataメソッドを利用して、ドラッグ&ドロップで受け渡しするデータの取得/設定を行えます。

例えば、以下は、dragstartハンドラにおいてsetDataメソッドでドラッグ元のidを設定して、dropハンドラでその情報を取得する例です。

[サンプル]DataTransferオブジェクトによるデータの設定と取得(HTML5_3_sample4.html)

    ・・・ ・・・
  //ドラッグ開始時のイベントハンドラ
  function dragstart(e){
    e.target.style.borderColor = "red";
    e.target.innerHTML = e.target.id+"をドラッグ開始";
    //ドラッグ要素の情報をDataTransferオブジェクトe.dataTransferに設定
    e.dataTransfer.setData("text", e.target.id);
  }
    
    ・・・ ・・・
  //ドロップ時のイベントハンドラ
  function drop(e){
    e.target.style.backgroundColor = "chartreuse";
    e.target.style.borderColor = "green";
    //DataTransferオブジェクトe.dataTransferからドラッグ要素で設定した情報を取り出して表示
    e.target.innerHTML = "ドロップ!("+e.dataTransfer.getData("text")+")";
    e.preventDefault();
  }
 図6:ドラッグ元の情報をドロップ先で使用(クリックで拡大)

dragstartメソッドにおいて、ドラッグ元要素のidを表すe.target.idの内容を、setDataを使用して、DataTransferオブジェクトに格納します。setDataの第1引数は、キー文字列になっています。キーには、値のMIMEタイプかtext(テキスト情報)、uri(URIのリスト)といった値を設定できます。

dropメソッドにおいて、getDataを使用して、DataTransferオブジェクトから、指定したキーに関連付いている値を取得できます。ここでは、格納時に使用した"text"を指定して、ドラッグ元要素のidを取得しています。

ブラウザ外部データのドロップ

ブラウザの外のデータをドロップする事もできます。ブラウザ内のドロップと同様にdropのイベントハンドラでdataTransfer.getDataメソッドを使用します。引数にはMIMEタイプを設定します。"text"は"text/plain"と同じ意味です。先ほどのサンプルコードのままでテキストエディタから、テキストのコピーができます。

 図7:テキストエディタの文章をドラッグ(クリックで拡大)

テキストエディタの文章を選択してドラッグをします。

 図8:dropイベントハンドラのある要素へドロップ(クリックで拡大)

テキストをそのまま2番目のdiv要素にドロップすると、ドロップ先要素にテキストエディタの値がコピーされます。

 図9:ドラッグ元の内容がコピーされる(クリックで拡大)

ローカルファイルをブラウザ上から読み込む - ファイルAPI

HTML4以前でもアップロード用のフォームはありましたが、選択されたファイルをJavaScriptで操作する事はできませんでした。HTML5では、ユーザーが選択したファイルをブラウザ上で読み取り操作するためのFile APIという機能があります。これによって、HTMLの技術のみを用いて、クライアント側で入力ファイルの処理を行うローカルアプリケーションの作成が可能になります。

それでは早速、サンプルを見ていきましょう。以下は、ファイルコントロールで指定された、またはドラッグ&ドロップされたファイルを読み込み、そのファイル情報をリスト表示するものです。

なお、サンプルはFirefox、Chromeで全ての機能が動作します。その他のブラウザでは、以下の制限がありますので、注意してください。

  • IE9ではFile APIは実装されていません。
  • Safariは一部実装されていますが、FileReaderオブジェクトを利用したファイル本文の表示はできません(ファイル情報の取得のみ可能)。
  • Operaはドラッグ&ドロップを使用できません。

以下は、サンプルの実行結果です。ファイルをドロップ要素にドラッグすると、ファイルの情報を一覧表示します。

 図10:ドラッグ&ドロップによるファイル選択(クリックで拡大)
 図11:ファイルの情報表示(クリックで拡大)

読み込みファイルを指定するためのHTML

ユーザーにファイルを指定させるためには、<input type="file">要素、または前節のドラッグ&ドロップ機能を利用します。input要素でmultiple属性を指定する事で、ファイルを複数選択できるようにする事もできます。

また、以下のサンプルでは、後からファイルの情報を表示するためのテーブルも配置しています。

[サンプル]ファイルコントロールとドロップ領域のdiv要素のHTML(HTML5_3_sample5.html)

  <h1>ファイルAPIサンプル</h1>
  以下のコントロールでファイルを選択するか下の領域にドロップしてください。
  <form name="form1">
    <input id="selectedFiles" type="file" multiple>
    <div id="dropedFiles" class="dropDiv" >ここにファイルをドロップしてください。</div>
  <h3>選択されたファイルのファイル情報</h3>
  <table>
    <thead><tr><th>名前</th><th>MIME Type</th><th>サイズ(bytes)</th></tr></thead>
    <tbody id="fileInfoList"></tbody>
  </table>
  </form>

イベントとハンドラの関連付け

続いて、ユーザーがファイルを選択した時のイベントにハンドラを関連付けます。input要素を使用する場合はchangeイベント、ドロップを使用する場合は、ドロップ領域を表す要素のdropイベントを利用します。

これらのイベントに後で定義するdisplayFileInfoメソッドを関連付けます。

[サンプル]ファイルリストを選択した時のイベントハンドラの設定(HTML5_3_sample5.html)

  //ウィンドウのloadイベントに下記の初期化メソッドinitを関連付ける
  window.addEventListener("load",init,true);
  //初期化メソッド各要素にイベントハンドラを設定する
  function init(){
    var selected = document.getElementById("selectedFiles");
    var droped = document.getElementById("dropedFiles");
      ・・・ (途中略)・・・
    //ファイルコントロールのchangeイベントと
    //divのdropイベントでファイル情報を読み取るイベントハンドラ設定
    selected.addEventListener("change",displayFileInfo,true);
    droped.addEventListener("drop",displayFileInfo,true);
  }

FileList、Fileオブジェクトの取得

イベントハンドラdisplayFileInfoでは、選択されたファイルリストの、全てのファイル情報の一覧表示を行っています。

[サンプル]ファイル情報を読み取って一覧表示(HTML5_3_sample5.html)

  //イベント引数からFileListオブジェクトを取得
  function getFiles(e){
    var files;
    //e.target.filesが空でない場合はファイルコントロール、それ以外はドロップだったと判断
    if(e.target.files){
      files = e.target.files;//(1)
    }else{
      files = e.dataTransfer.files;//(2)
    }
    return files;
  }
  //FileListオブジェクトのFileの情報(名前、MIMEタイプ、サイズ(バイト))を一覧表示
  function displayFileInfo(e){
    var files = getFiles(e);
    //ファイル情報一覧表示用テーブルのtbody要素を取得
    var fileInfo = document.getElementById("fileInfoList");
    fileInfo.innerHTML = "";
    var tr,file;
    for(var i = 0; i < files.length; i++){
      file = files[i];
      //ファイル情報一覧表示用テーブルの新しい行tr要素を生成して各ファイル情報をセルに詰める
      tr = document.createElement("tr");
      tr.innerHTML +="<td>"+file.name+"</td>";
      tr.innerHTML +="<td>"+file.type+"</td>";
      tr.innerHTML +="<td>"+file.size+"(bytes)</td>";
      //作成した行をtbodyの子要素に追加する
      fileInfo.appendChild(tr);
    }
  }

FileListオブジェクトは、それぞれ以下のように取得できます。

  1. changeイベントの引数eから、発生元のファイルコントロールe.targetのfilesを参照
  2. ドロップを使う方法では、イベント引数eから、e.dataTransfer.filesを参照

FileListオブジェクトは、ファイル情報(Fileオブジェクト)の集合です。サンプルでは、ここからFileオブジェクトをひとつひとつ取り出して、テーブルに名前、MIMEタイプ、サイズなどの情報を表示しています。以下にFileオブジェクトで利用できる主なプロパティをまとめます。

表3:Fileオブジェクトのプロパティ

プロパティ名 説明
name 名前
type MIME タイプ
size サイズ(バイト単位)
lastModifiedDate 最終更新日時
  • ドラッグ&ドロップAPI、File API、Web StorageのHTMLサンプル

著者
飯島 聡(著)山田 祥寛(監修)
WINGSプロジェクト

有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表:山田祥寛)。おもな活動は、Web開発分野の書籍/雑誌/Web記事の執筆。ほかに海外記事の翻訳、講演なども幅広く手がける。2011年3月時点での登録メンバは36名で、現在もプロジェクトメンバーを募集中。執筆に興味のある方は、どしどしご応募頂きたい。著書多数。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています