ちゃんとHTML5を理解しよう Drop Drag API
|File APIとDrop Drag APIを組み合わせてDrop Drag APIを理解してみます。
Drop Drag APIを学ぶ
Drop Drag APIを利用しなくてもmousedown、mousemove、mouseupイベントにロジックを記述ることでDOMのドラッグは可能です。
HTML5で追加されたAPIを利用するメリットを考えてみましょう。
Drop Drag APIとは
HTML5でDataTransferが追加されました。
Drop DragはDataTransferのイベントを介して実現しますが、従来の方法と異なってデータの送信側と受信側を同じwindow内に限定しません。
その為、デスクトップからテキストをDragしたりDOM(リンク先)をデスクトップにDragする事が可能になります。
Drop Drag APIの基本
Drop Drag APIを試すために最初にhtmlとcssの準備を行いましょう。
まずhtmlです。
Dragする要素にdraggable=trueを設定してDrag可能な状態にします。
<ul id="drag"> <li draggable="true" class="li-drag">ドラッグ出来るよ!</li> <li draggable="false">ドラッグ出来ません</li> <li draggable="true" class="li-drag">動かしてみよう!</li> </ul> <div id="dropArea"> <h2>Drop Here!</h2> <span id="dropText"></span> </div>
Dropするエリアを見やすくするためにCSSを追加します。
ul#drag{ margin:0; padding:0 } #drag li{ border:1px solid #ccc; list-style:none; margin-bottom:10px; padding:10px; text-align:center; width:200px; } #drag li.li-drag:hover{ background-color:#ccc; cursor :move; } #dropArea { border:1px solid #ccc; height:500px; text-align:center; width:500px; } span#dropText { color:#ff1818; }
ロジックを記述していきます。
まずDrag側でDragするデータの設定をsetDataメソッドで行います。
//Drag $('#drag li').each(function(e){ $(this).on('dragstart',function(e){ var _e = e.originalEvent; _e.dataTransfer.setData('text/plain',_e.target.textContent); _e.dataTransfer.setData('text/html',_e.target.outerHTML); _e.dataTransfer.setData('text/uli-list',document.location.href); }); });
次にDrop側のロジックです。
drag可能な要素がdropエリア上にあるとdragoverイベントが発生します。
dragoverイベントの処理中にdropイベントを発生させるために意図的にpreventDefault()を呼び出してdropイベントを呼び出します。
dropイベント内で設定したデータをgetDataメソッドで受け取ります。
preventDefault()を呼び出さない場合はブラウザデフォルトの挙動となりdropイベントが呼ばれません。例えば、デスクトップのテキストファイルをドロップするとブラウザデフォルトの挙動でブラウザ内で展開が行われたりします。
//Drop $('#dropArea').on('dragover',function(e){ var _e = e.originalEvent; $.each(_e.dataTransfer.types,function(key,val){ if(val==="text/plain"){ _e.preventDefault(); return; } }); }); $('#dropArea').on('drop',function(e){ var _e = e.originalEvent; _e.preventDefault(); var data = _e.dataTransfer.getData('text/plain'); $('#dropText').html(data); });
動作確認してみましょう。
大丈夫そうですね!
Drop Drag APIの応用
ローカルのファイルをDropしてみましょう。
File APIのコードがそのまま利用できます。
ローカルにテスト用のテキストファイルを準備して下さい。
こんにちは! ローカルのファイルですよ!
ロジックを修正してみましょう。
dragoverイベントのtypesチェックにFilesを追加します。
dropイベント内でファイルのdropかチェックを行い、ファイルの場合は内容を読み取ります。
//Drop $('#dropArea').on('dragover',function(e){ var _e = e.originalEvent; $.each(_e.dataTransfer.types,function(key,val){ if(val==="text/plain"){ _e.preventDefault(); return; }else if(val==="Files"){ _e.preventDefault(); return; } }); }); $('#dropArea').on('drop',function(e){ var _e = e.originalEvent; _e.preventDefault(); if(0<_e.dataTransfer.files.length){ var file = _e.dataTransfer.files[0]; var reader = new FileReader(); reader.readAsText(file); reader.onload = function(event){ $('#dropText').html(file.name + 'を選択しました!<br />' + event.target.result); } }else{ var data = _e.dataTransfer.getData('text/plain'); $('#dropText').html(data); } });
出来上がったサンプルコード
<!DOCTYPE html> <html lang="ja-JP"> <head> <meta charset="UTF-8"> <style> ul#drag{ margin:0; padding:0 } #drag li{ border:1px solid #ccc; list-style:none; margin-bottom:10px; padding:10px; text-align:center; width:200px; } #drag li.li-drag:hover{ background-color:#ccc; cursor :move; } #dropArea { border:1px solid #ccc; height:500px; text-align:center; width:500px; } span#dropText { color:#ff1818; } </style> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script> $(function(){ //Drag $('#drag li').each(function(e){ $(this).on('dragstart',function(e){ var _e = e.originalEvent; _e.dataTransfer.setData('text/plain',_e.target.textContent); _e.dataTransfer.setData('text/html',_e.target.outerHTML); _e.dataTransfer.setData('text/uli-list',document.location.href); }); }); //Drop $('#dropArea').on('dragover',function(e){ var _e = e.originalEvent; $.each(_e.dataTransfer.types,function(key,val){ if(val==="text/plain"){ _e.preventDefault(); return; }else if(val==="Files"){ _e.preventDefault(); return; } }); }); $('#dropArea').on('drop',function(e){ var _e = e.originalEvent; _e.preventDefault(); if(0<_e.dataTransfer.files.length){ var file = _e.dataTransfer.files[0]; var reader = new FileReader(); reader.readAsText(file); reader.onload = function(event){ $('#dropText').html(file.name + 'を選択しました!<br />' + event.target.result); } }else{ var data = _e.dataTransfer.getData('text/plain'); $('#dropText').html(data); } }); }); </script> </head> <body> <ul id="drag"> <li draggable="true" class="li-drag">ドラッグ出来るよ!</li> <li draggable="false">ドラッグ出来ません</li> <li draggable="true" class="li-drag">動かしてみよう!</li> </ul> <div id="dropArea"> <h2>Drop Here!</h2> <span id="dropText"></span> </div> </body> </html>