ネイティブのドラッグアンドドロップはdragstart、drag、dragendイベントを通じて実装されます。ただし、これは単なるドラッグ アンド ドロップです。IE6 と IE7 にはまだドラッグ アンド ドロップの問題があり、データ交換は実装されていません。データの交換を実現するために、IE5 では dataTransfer オブジェクトが導入されました。 dataTransfer オブジェクトはイベント オブジェクトのプロパティであり、ドラッグされた要素からドロップ ターゲットに文字列形式でデータを転送するために使用されます。 dataTransfer オブジェクトはイベント オブジェクトのプロパティであるため、ドラッグ アンド ドロップ イベントのイベント ハンドラー内でのみアクセスできます。イベント ハンドラーでは、このオブジェクトのプロパティとメソッドを使用して、ドラッグ アンド ドロップ機能を完了できます。
dataTransfer オブジェクトには、getData() メソッドと setData() メソッドという 2 つの主要なメソッドがあります。これら 2 つのメソッドの英語の文字通りの意味から、その用途を大まかに推測できます。 getData() メソッドは、setData() メソッドで保存した値を取得できます。 setData() メソッドの最初のパラメータは、getData() メソッドの唯一のパラメータでもあり、データ型を保存するために使用される文字列で、値は「text」または「URL」です。
IE は、「テキスト」または「URL」という 2 つの有効なデータ型のみを定義しますが、HTML5 はこれを拡張して、さまざまな MIME タイプを指定できるようにします。下位互換性のために、HTML5 は「text」または「URL」もサポートしますが、これら 2 つのタイプは「text/plain」または「text/url-list」にマップされます。
実はdataTransferオブジェクトはMIMEタイプごとに値を保存することができます。言い換えれば、同僚がこのオブジェクトにテキストと URL を保存しても、他に問題はありません。ただし、dataTransfer オブジェクトに格納されているデータは、drop イベント ハンドラーでのみ読み取ることができます。データが ondrop ハンドラーで読み取られない場合、dataTransfer オブジェクトは破棄され、データは失われます。
テキスト ボックス内のテキストをドラッグすると、ブラウザは setData() メソッドを呼び出して、ドラッグしたテキストを dataTransfer オブジェクトに「テキスト」形式で保存します。同様に、リンクまたは画像をドラッグ アンド ドロップすると、setData() メソッドが呼び出され、URL が保存されます。次に、これらの要素をドロップ ターゲットにドラッグ アンド ドロップすると、getData() メソッドを通じてデータを読み取ることができます。もちろん、開発者は、後で使用できるように、dragstart イベント ハンドラーで setData() を呼び出して、転送するデータを手動で保存することもできます。
データをテキストで保存するのとURLとして保存するのは違います。データをテキスト形式で保存した場合、データは特別な処理を受けません。 URL 形式で保存すると、ブラウザはそれを Web ページ内のリンクとして扱います。この URL を別のブラウザ ウィンドウに配置すると、その URL を開くことができます。
Firefox 5 以前のバージョンでは、「url」と「text」を「」と「text/plain」にマッピングできません。ただし、「Text」(大文字の T) を「text/plain」にマッピングできます。クロスブラウザーの状況で dataTransfer オブジェクトからデータをより適切に取得するには、URL データを取得するときに 2 つの値を検出し、テキスト データを取得するときに「Text」を使用するのが最善です。
注: IE10 とそれ以前のバージョンではまだ拡張 MIME タイプ名がサポートされておらず、認識できないデータ タイプが発生するとエラーが報告されるため、必ず短いデータ タイプを最初に指定してください。ただし、「text」または「URL」の値は IE でのみ必須であり、Firefox 3.6 以降、Chrome、Opera では他の値を使用して文字列を設定することもできます。
dataTransferオブジェクトを使用すると、データを転送するだけでなく、ドラッグされた要素や配置対象の要素がどのような操作を受け取れるかをdataTransferオブジェクトを通じて決定することができます。このような機能を実現するには、dropEffect 属性とeffectAllowed 属性を使用します。
このうち、dropEffect 属性を通じて、ドラッグされた要素がどのような動作を実行できるかを知ることができます。この属性の 4 つの値は次のとおりです:
none: ドラッグされた要素をここに配置できません。これは、テキスト ボックスを除くすべての要素のデフォルト値です。
move: ドラッグされた要素をドロップターゲットに移動する必要があります。
copy: ドラッグされた要素をドロップターゲットにコピーする必要があります。
リンク: ターゲットを配置すると、ドラッグされた要素が開きます (ただし、ドラッグされた要素は URL アドレスを持つリンクである必要があります)。
要素をドロップ ターゲットにドラッグすると、上記の各値によりカーソルが異なるシンボルとして表示されます。
dropEffect属性だけでは効果がありません。これは、effectAllowed 属性と組み合わせて使用した場合にのみ有効になります。 effectAllowed 属性は、要素のドラッグのどの動作が許可されるかを示します (dropEffect)。 effectAllowed 属性にも多くの値があり、その値は次のとおりです:
uninitialized: ドラッグされた要素には配置動作が設定されていません。
none: ドラッグされた要素はいかなる動作も行うことができません。
copy: 値「copy」を持つdropEffectのみが許可されます。
link: 値「link」を持つdropEffectのみが許可されます。
move: 値「move」を持つdropEffectのみが許可されます。
copyLink: 「copy」と「link」の値を持つdropEffectを許可します。
copyMove: 「copy」と「move」の値を持つdropEffectを許可します。
linkMove: 「link」と「move」の値を持つdropEffectを許可します。
all: 任意のdropEffectを許可します。
effectAllowedプロパティを設定するには、ondragstartイベントハンドラーで設定する必要があります。小さな例は次のとおりです
HTMLコード
<ul> <li draggable="true">梦龙小站</li> <li draggable="true">梦龙小站</li> <li draggable="true">梦龙小站</li> </ul> <a href="http://www.baidu.com/">梦龙小站</a> <p id="p1">梦龙小站</p>
CSSコード
li{ width:100px; height:30px; border:1px #000000 solid; margin:20px; list-style:none;} #p1{ width:100px; height:100px; background:red; margin:300px;}
JavaScriptコード
//dataTransfer对象 : 连接拖拽细节的 ,在event对象下面的 //拖动不带链接的li,会起作用但不跳转链接 //拖动带连接的a,会起作用也跳转 window.onload = function(){ var aLi = document.getElementsByTagName('li'); var aA = document.getElementsByTagName('a'); var op = document.getElementById('p1'); for(var i=0;i<aLi.length;i++){ aLi[i].ondragstart = function(ev){ //拖拽前触发 this.style.background = 'yellow'; ev.dataTransfer.setData('a','hello'); //存储一个键值对 : value值必须是字符串 ev.dataTransfer.effectAllowed = 'all'; ev.dataTransfer.setDragImage(this,0,0); }; aLi[i].ondragend = function(){ //拖拽结束触发 this.style.background = ''; }; } for(var i=0;i<aA.length;i++){ aA[i].ondragstart = function(ev){ //拖拽前触发 this.style.background = 'yellow'; ev.dataTransfer.setData('a','hello'); //存储一个键值对 : value值必须是字符串 ev.dataTransfer.effectAllowed = 'link'; ev.dataTransfer.setDragImage(this,0,0); }; aA[i].ondragend = function(){ //拖拽结束触发 this.style.background = ''; }; } op.ondragenter = function(){ //相当于onmouseover this.style.background = 'green'; }; op.ondragleave = function(){ //相当于onmouseout this.style.background = 'red'; }; op.ondragover = function(ev){ //进入目标、离开目标之间,连续触发 ev.preventDefault(); //阻止默认事件:元素就可以释放了 ev.dataTransfer.dropEffect = 'link'; //真对外部文件 }; op.ondrop = function(ev){ //释放鼠标的时候触发 this.style.background = 'red'; alert( ev.dataTransfer.getData('a') ); }; };