#はじめに
ファイルを選択するフォームがある際、
ドラッグ&ドロップができるとスマートで便利ですよね。
mulitiple属性がつくと複数のファイルを一つのフォームで送信が可能です。
そうした上でドラッグ&ドロップで選択する仕様にするのはさほど難しくはありませんでした。
しかし、複数同時にドロップするのではなく、
その複数のファイルを一個ずつドロップできるようにしたかったのですが...
ちょっとツマってしまったので、その解決方法をメモ。
#実装
<form action="~~~" accept-charset="~~~" method="post">
<input multiple="multiple" type="file" name="task_images" id="task_images">
<div id="dropZone" style="width:~~~px;height:~~~px;">
ここにドラッグ&ドロップ
</div>
<input type="submit">
</form>
"~~~~"
やname="task_images"
は例です。
ここでは扱うファイルを画像ファイルを想定してます。
idの"task_images"
"dropZone"
でそれぞれの要素を取得していきます。
var fileField = document.getElementById('task_images');
var dropZone = document.getElementById('dropZone');
var dt = new DataTransfer();
dropZone.addEventListener('drop', (e)=>{
e.preventDefault();
dt.items.add(e.dataTransfer.files[0]);
fileField.files = dt.files;
});
dt
に代入されたDataTransferオブジェクト
はドラッグ&ドロップされたデータを扱う、保持するために使われます。
なお、safariとIEはnew
に対応していないので注意!
e.preventDefault();
がないとドロップできないので大事です。
dt.items
はDataTransferItemListオブジェクト
dt.files
とe.dataTransfer.files
はFileListオブジェクト
です。
e.dataTransfer.files[0]
はFileオブジェクト
です。
非常にややこしい!
e.dataTransfer.files
にはドロップされたファイル(Fileオブジェクト
)がFileListオブジェクト
の中に同時にドロップされた数だけ格納されています。
今回は一つずつドロップし選択するのでe.dataTransfer.files[0]
をadd
メソッドでdt.items
に追加します。
そうするとdt.files
にFileListオブジェクト
として変更が反映されています。
最後にinputエレメントであるfileField
のfiles
をdt.files
に差し替えます。
これでドロップによってinputのファイル選択を追加していくことができます。
#最後に
DataTransferにはclearData()など応用の利くメソッドがあるので、
使いようによってはファイル数の制限も実装できます。
画像プレビューにも使うこともできるので、ぜひ調べて見てください。
#参考
DataTransfer
Document: drop イベント
FileListは作れる!~file inputの中身も自由自在~