こんにちは。
セミが鳴き出しましたね。夏、嫌な季節です。
さて、Macで良いリネームアプリを探しているのですが、
なかなか決定版が見つからずに嘆いています。
そんな時ふと思いました。
(使ったことないけど)HTML5のFileAPI使えばリネームって出来るんじゃないか?
あと、いちいちファイルをチューザーからファイルを選択するのも面倒だし、
HTML5のDrag&DropAPI使ってブラウザにファイルをドロップできるようにしよう!
と思いFileAPIとDrag&DropAPIを調べてみたら、
ちょっとした小物を作るのにも地味に面倒だったのでメモを残します。
File APIとは、HTML5で提供されているAPIです。
ローカルファイルやディレクトリの読み書きが出来るオブジェクトです。
例えば、バイナリデータを扱うBlob
や、
ファイルの読み取りを行うFileReader
などがあります。
ファイルの書き込みが出来るインタフェースもあるのですが、
まだChromeのみしか実装を終えておらず、限定的な環境だったので、
リネームツールは諦めて、単にファイルの情報を読取ることを目的としました。
Drag&Drop APIとは、ページ内の要素をドラッグ可能にしたり、
そのまま要素へのドロップを可能にするAPIです。
ウェブページ内の要素やローカル環境に保存されたファイルなどのデータを、
マウスで引きずるように移動させて他の場所に置く操作のことです。
HTML5以前にも、mousedownやmouseupなどのイベントで実現することはできましたが、
HTML5ではドラッグ&ドロップ専用の新しいイベントや新しいメソッド・属性が追加されています。
ドラッグ&ドロップ-HTML5のAPI、および、関連仕様
簡単に各APIの概要を追ったところで、本題です。
通常、ブラウザへファイルをドロップすると、そのファイルが開かれると思います。
画像をドロップすればその画像が表示されます。
プログラムやCSSのファイルならその内容が表示されます。
HTMLファイルをドロップすれば、そのHTMLを解釈した結果が確認できと思います。
このようにファイルをブラウザにドロップする操作は、
イベントなのでjsでキャンセルができます。
つまりどういうことかと言うと、
サンプルページを用意したので、適当なファイルをドロップしてみて下さい。
如何でしょう。 枠の中にファイルをドロップしても何も起こらないと思います。
従来ブラウザにファイルをドロップした時に起きるイベントを、
すべてキャンセルしています。
まとめると、
ブラウザのデフォルトの挙動をキャンセルして、
独自のイベントハンドラを書くことで、
ファイルがドロップされたことを検知し、扱うことが可能になる
と言うことです。
先ほどのサンプルで、
ファイルのドロップイベントを受け取ることが出来るようになったので、
次はドロップされたファイルを読み取ってみようと思います。
ただ単にファイル名、ファイルサイズ、ファイルの種類を取得するだけなら、
FileReaderを使わずに取得できます。
ただし、ファイルの内容を読み取るには、
FileAPIのFileReader
インタフェースを使います。
ざっとサンプルコードを。
動作確認はこちらからできます。
ドロップされたファイルは、dropイベントに渡されるeventオブジェクトから取得出来ます。
e.originalEvent.dataTransfer.files
でドロップされたファイルにアクセスできます。
filesと複製形になっていることから分かるように、
複数のファイルをまとめてドロップしても、まとめて取得できます。
取得したファイルは、FileList
オブジェクトというものになっており、
配列のように各要素にブラケット([]
)でアクセスできますが、
配列ではありません。
こんな感じ。
関数に渡されるargumentsのようなオブジェクトです。
なので、配列のメソッドをそのまま使うことができません。
エラー。
ただ、argumentsと同じように、callを使うことで配列に変換出来ます。
用途によりますが、配列にしておいたほうが使える範囲が広がると思います。
var tmp = e.originalEvent.dataTransfer.files, files = Array.prototype.slice.call(tmp); console.log(Array.isArray(tmp)); // false console.log(Array.isArray(files)); // true
おそらくイベント名を見ればお察しかと思いますが、
このサンプルで使っているイベントの簡単な説明を。
dragenter
dragover
dragleave
drop
FileReader.onload
e.target.result
で取れますこれらのサンプルを手軽に利用できるように、jQueryプラグイン化してみました。
サンプルはこちらから確認できます。
先ほどのサンプルのまんまでは面白く無いので、
画像がドロップされたら、その画像を表示するという処理を入れてみました。
文字列から画像を復元する方法については、また別途記事を書こうと思います。
使い方はこんな感じです。
jQuery.filedrop.jsは4つのオプションを提供します。
ファイルの読み取りは簡単なのに、書き込みがファイルの面倒でした。。。
ドラッグ&ドロップについては、
APIがなくても、mouseoverやmousedownを使って書けますが、
APIを用いたほうが可読性が高く柔軟なコードになると思います。
環境に制限が無いなら、こちらを使ってみるといいと思います。
最後に、jQuery.filedrop.jsのソースはGistに上げてあります。
最期まで読んで頂き、ありがとうございました!