HTML5 Drag&Drop 同瀏覽器跨文件拖拉
Sat, 09 Oct 2010 19:42:41 +0800除了跨應用軟體間的drag&drop,另外一個可以測試的是同一瀏覽器但是不同視窗不同文件之間的drag&drop。其實使用的方式跟前面兩篇文章:HTML5 Drag&Drop + 純AJAX檔案上傳以及一個簡單的HTML5 Drag & Drop試作差不多。目前測試到比較可用的方式,是過濾Event.dataTransfer.types,看看裡面是否有一筆資料為'text/uri-list',然後用Event.dataTransfer.getData('text/uri-list')就可以取得拖拉檔案的網址,接下來就可以使用這個資料來做一些處理。
如果要讓網頁可以同時處理其他應用軟體與跨文件drag&drop,我想到比較好的方式是先透過Event.dataTransfer.types裡面是否有'Files'字串來判斷(DataTransfer.types)。但是這時發現Firefox4 Beta6有一個問題...Orz。在從另一個Firefox視窗拖曳圖檔進來時,並沒有在Event.dataTransfer.files設定檔案資料,但是Event.dataTransfer.types卻有一筆資料是'Files',這樣會造成原本的程式邏輯有問題。所以只好額外用Event.dataTransfer.files.length來判斷是否有檔案資料。
利用這樣的判斷方式,就可以在有圖檔的File物件收到時,上傳檔案並且顯示上傳後的檔案。如果收到的資料是圖檔的url,就利用這個url來顯示圖檔。以下是從前兩篇文章再做修改的測試:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
span#panel {
display: inline-block;
background: #336699;
width: 140px;
height: 180px;
border: solid black 2px;
border-radius: 10px;
padding: 5px;
text-align: center;
color: white;
vertical-align: middle;
}
span {
display: inline-block;
vertical-align: middle;
}
div.msg {
display: block;
background: #6699CC;
width: 480px;
height: 50px;
border: solid black 2px;
border-radius: 10px;
padding: 5px;
text-align: center;
color: white;
margin: 1px;
vertical-align: middle;
}
div#container {
vertical-align: baseline;
border: solid 1px white;
padding: 5px;
text-align: center;
}
</style>
<script src="fwajax3.js"></script>
</head>
<body>
<div style="text-align:center"><h4>HTML5 Drag&Drop with pure AJAX file upload test.</h4></div>
<div id="container"><span id="panel">Drop image here.<br></span> <span><div class="msg" id="msg1"></div><div class="msg" id="msg2"></div><div class="msg" id="msg3"></div></span></div>
</body>
</html>
<script>
document.ondragenter = function(e){e.preventDefault();}
document.ondragover = function(e){e.preventDefault();}
document.getElementById('panel').addEventListener('dragenter', function(e){
e.preventDefault();
if(window.console) console.log('dragenter');
e.effectAllowed = ['move'];
},false);
document.getElementById('panel').addEventListener('dragover', function(e){
e.preventDefault();
if(window.console) console.log('dragover');
e.dataTransfer.dropEffect = 'move';
},false);
document.getElementById('panel').addEventListener('drop', function(e){
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
if(window.console) console.log('drop');
if(window.console) console.log(e.dataTransfer);
if(e.dataTransfer.types && e.dataTransfer.types.length>0) {
var isFile = false;
for(var i=0; i<e.dataTransfer.types.length; i++) {
if(e.dataTransfer.types[i] === 'Files' && e.dataTransfer.files.length>0) isFile = true;
}
for(var i=0; i<e.dataTransfer.types.length; i++) {
if(window.console) console.log(e.dataTransfer.types[i]);
if(e.dataTransfer.types[i]==='Files') {
if(e.dataTransfer.files.length>0) {
for(var j=0; j<e.dataTransfer.files.length; j++) {
switch(e.dataTransfer.files[j].type) {
case 'image/jpeg':
case 'image/gif':
case 'image/png':
case 'image/bmp':
document.getElementById('msg1').innerHTML = 'File name: <br>'+e.dataTransfer.files[j].name;
document.getElementById('msg2').innerHTML = '';
document.getElementById('msg3').innerHTML = '';
setTimeout(function(blob){
return function() {
var fileReader = new FileReader();
fileReader.onload = function() {
if(window.console) console.log('got an image file.');
//if(window.console) console.log(this.result);
var uploader = new fwH5AjaxUploader(
'save_ajax.php',
function(_txt,_xml) {
if(window.console) console.log(_txt);
var msg = JSON.parse(_txt);
if(msg.state == 'success') {
document.getElementById('msg3').innerHTML = 'File uploaded: <br>'+blob.name;
var img = document.createElement('img');
img.src = msg.path;
img.width = '110';
img.style = "text-align:center";
document.getElementById('panel').innerHTML = 'Drop Here.<p>';
document.getElementById('panel').appendChild(img);
img = null;
}
}
);
uploader.addFile(
'fileupload',
{'name':blob.name,'type':blob.type,'data':this.result.slice(this.result.indexOf(",")+1)},
'base64'
);
document.getElementById('msg2').innerHTML = 'Start uploading: <br>'+blob.name;
uploader.send();
};
try {
fileReader.readAsDataURL(blob);
} catch(e) {
alert(e);
}
};
}(e.dataTransfer.files[j]),100);
break;
default:
alert('Only image file allowed.\nIncluding: jpeg, png, gif and bmp.');
break;
}
}
}
}
if(!isFile && e.dataTransfer.types[i]!=='Files') {
var type = e.dataTransfer.types[i];
if(window.console) console.log(type);
if('text/uri-list' === type || 'text/x-moz-url' === type) {
var msg = e.dataTransfer.getData(type);
if(window.console) console.log(msg);
var filename = msg.split('/')[msg.split('/').length-1].split('?')[0];
var allowed = ['jpg','gif','png','bmp'];
var isAllowed = false;
for(var m=0; m<allowed.length; m++) {
if(filename.toLowerCase().indexOf(allowed[m])>-1) {
isAllowed = true;
break;
}
}
if(isAllowed) {
var img = document.createElement('img');
img.src = msg;
img.width = '110';
var panel = document.getElementById('panel');
panel.innerHTML = 'Drop Here.<p>';
panel.appendChild(img);
document.getElementById('msg1').innerHTML = 'File name: <br>' + msg.split('/')[msg.split('/').length-1];
document.getElementById('msg2').innerHTML = 'Linked from: <br>' + msg;
document.getElementById('msg3').innerHTML = 'Linked.';
} else {
alert('Only image file allowed.\nIncluding: jpeg, png, gif and bmp.');
}
}
}
}
}
},false);
</script>
save_ajax.php以及fwajax3.js請參考前篇,程式是一樣的。
接下來看一下操作的截圖:
![]() |
| 這是跨文件拖拉圖檔,會直接使用url |
![]() |
| 這是從系統拖拉圖檔上傳的結果 |
2010-10-9 19:56 補充:
仔細觀察了一下DataTransfer物件,發現從Chrome7拖拉網頁中的圖檔到Firefox4時,會收到的資料主要是'text/uri-list',但是從Firefox4拖拉網頁中的圖檔到Chrome7時,會收到File物件及'text/uri-list'。我測試程式的邏輯有一點混亂,不過我不想再調整了...不過同時收到File物件及'text/uri-list'時,還是做一下判斷比較好,在不需要上傳檔案的情況下,也許直接使用url就可以了。

