cheka.jp 超不定期で更新する写真達。お口直しにどうぞ。

ちゃんとHTML5を理解しよう Drop Drag API

File APIとDrop Drag APIを組み合わせてDrop Drag APIを理解してみます。

W3C HTML5 Logo

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);
});

動作確認してみましょう。

Dragテスト

大丈夫そうですね!

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>

Add a Comment

メールアドレスが公開されることはありません。